Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Volguus
Mar 3, 2009

CPColin posted:

I'm spending far too much time trying to figure out what URL a certain API endpoint should live on. The request is going to be "get me the permissions user X has on application Y," so both X and Y definitely need to be in the URL, but I'm not planning to allow "get me all permissions user X has" or "get me all users application Y has," so I'm probably overthinking it and should just use /permissions?user=X&application=Y instead of the typical RESTful hierarchical-ish style.

I'm Not Gonna Need It™

POST api/V1/GetPermissionUserApp with GetPermissionRequest { User: user, App:app}, returns 200 OK GetPermissionResponse{Permission: permission}

Adbot
ADBOT LOVES YOU

CPColin
Sep 9, 2003

Big ol' smile.
I'm just going to set all the parameters as request headers and put the user's permissions in the response headers. That way, I can have Content-Length: 0 and save a bunch of bandwidth!!!

poemdexter
Feb 18, 2005

Hooray Indie Games!

College Slice

CPColin posted:

I'm spending far too much time trying to figure out what URL a certain API endpoint should live on. The request is going to be "get me the permissions user X has on application Y," so both X and Y definitely need to be in the URL, but I'm not planning to allow "get me all permissions user X has" or "get me all users application Y has," so I'm probably overthinking it and should just use /permissions?user=X&application=Y instead of the typical RESTful hierarchical-ish style.

I'm Not Gonna Need It™

GET /user/X/permissions/Y

GET /user/X?permissions=Y

Volguus
Mar 3, 2009

poemdexter posted:

GET /user/X/permissions/Y

GET /user/X?permissions=Y

How does it feel to be so wrong?

Fellatio del Toro
Mar 21, 2009

tbh I could not care less about True RESTful Standards or what HTTP methods you use or how you pass args as long as you provide some sort of OpenAPI/etc schema so I can generate a client

poemdexter
Feb 18, 2005

Hooray Indie Games!

College Slice

Volguus posted:

How does it feel to be so wrong?

I couldn't tell you. I'll let you know when it happens though.

Nomnom Cookie
Aug 30, 2009



Xarn posted:

How does it feel to be so wrong? :v:

Wrong about what? My observations, after integrating with a couple dozen data providers, of what factors impact my ability to quickly and correctly implement an API consumer? It really doesn't help me at all if every single endpoint fits neatly into a taxonomy.

Xarn
Jun 26, 2015
Returning

code:
200 OK

{ status : lol gently caress you, wrong auth }
should be a stabbable offense.

Same goes for POSTing to a GetFoo endpoint to get information about Foo and other "well documented" stupidities.

ChickenWing
Jul 22, 2010

:v:

Blind adherence to RESTfulness is bad, much like blind adherence to literally any other paradigm in the universe is bad.


"whats HTTP verbs precious" is worse though, because you're throwing out volumes of implicit information because you've chosen not to give a poo poo, and now your consumer needs to read a loving novel to find out how to create a single resource in your application

Kevin Mitnick P.E. posted:

Wrong about what? My observations, after integrating with a couple dozen data providers, of what factors impact my ability to quickly and correctly implement an API consumer? It really doesn't help me at all if every single endpoint fits neatly into a taxonomy.

It actually probably would help you. I'm sorry you've had to develop against all these garbage APIs.

beuges
Jul 4, 2005
fluffy bunny butterfly broomstick

Bruegels Fuckbooks posted:

It's all bad, but anyone who puts an HTTP verb in the name of an api (e.g. GetFoo instead of having Foo with a GET verb) should be loving stabbed. I hate that poo poo.

There are some reasonable reasons behind it. The main one is that the entire API is consistent - every request and response is handled identically. Our API consumers are typically all written in C#, either ASP.net, other ASP web services, Xamarin, etc. So typically there's a single Task<ApiResponse<TResponse>> PerformRequestAsync<TRequest, TResponse>(string endpoint, TRequest request); method that does everything from setting credentials to handling the non-successful responses and setting the right error flags and whatever. If you are trying to get a Foo from the server, you don't have to craft your request any differently to if you are trying to create a Foo or do anything else.

code:

var createdFoo = await PerformRequestAsync<CreateFooRequest, CreateFooResponse>("CreateFoo", new CreateFooRequest() { . . . . . });
var theFoo = await PerformRequestAsync<GetFooRequest, GetFooResponse>("GetFoo", new GetFooRequest() { FooId = createdFoo.CreatedFooId });

Another reason was, if I get a 404 when doing a GET to api/Fooo/1, is it because Foo ID 1 doesn't exist, or endpoint Fooo doesn't exist.

It's not perfect, but it's consistent. Next project is going to be .net Core with proper REST controllers to see how which approach ends up less effort to develop against and maintain.

edit:

Xarn posted:

Returning

code:

200 OK

{ status : lol gently caress you, wrong auth }

should be a stabbable offense.

Same goes for POSTing to a GetFoo endpoint to get information about Foo and other "well documented" stupidities.

Philosophically, the request was successfully processed by the server (hence the 200 OK) and the result of it processing your request was that it determined you used the wrong auth, and should be hosed.

beuges fucked around with this message at 20:59 on Apr 5, 2019

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.
Philosophically you're now telling caching proxies that that was a valid request they should definitely cache. Well done.

beuges
Jul 4, 2005
fluffy bunny butterfly broomstick

Sagacity posted:

Philosophically you're now telling caching proxies that that was a valid request they should definitely cache. Well done.

But it was a POST to an endpoint called GetFoo, so it shouldn't be cached by anything.

Volguus
Mar 3, 2009

beuges posted:

Philosophically, the request was successfully processed by the server (hence the 200 OK) and the result of it processing your request was that it determined you used the wrong auth, and should be hosed.

Philosophically you have reinvented the wheel. All that code all those libraries written for you since the dawn of time are useless because you're doing everything all over again in your code, badly.

ChickenWing
Jul 22, 2010

:v:

beuges posted:

Philosophically, the request was successfully processed by the server (hence the 200 OK) and the result of it processing your request was that it determined you used the wrong auth, and should be hosed.

That's wrong, though. The server did not, in fact, successfully process the request, because if it had you would have the result of the request you made, unless that request was specifically "please get me the json body that says 'lol gently caress you, wrong auth'".

Nomnom Cookie
Aug 30, 2009



ChickenWing posted:

Blind adherence to RESTfulness is bad, much like blind adherence to literally any other paradigm in the universe is bad.


"whats HTTP verbs precious" is worse though, because you're throwing out volumes of implicit information because you've chosen not to give a poo poo, and now your consumer needs to read a loving novel to find out how to create a single resource in your application


It actually probably would help you. I'm sorry you've had to develop against all these garbage APIs.

Oh yeah, when I see GET/POST/PUT/PATCH/DELETE /foo in the swagger UI I'm good to go and definitely don't need to know what a foo is, what fields it has, what those mean, what happens when I PUT, what format I'm supposed to use for PATCH, and so on. You can develop a consistent and reasonable way to use HTTP verbs in your API, and if done well it can be helpful to consumers, but it's 4 bits of information max. It says very little and I will still need docs so I can learn what special qualities you have included that are definitely the right way to do things, unlike every other person who exposed something over HTTP and felt that verbs were very meaningful and important. They were morons who should be ignored.

ChickenWing
Jul 22, 2010

:v:

Like, do you just not throw exceptions because errors are the result of successfully processing your code and finding a problem?

ChickenWing
Jul 22, 2010

:v:

Kevin Mitnick P.E. posted:

Oh yeah, when I see GET/POST/PUT/PATCH/DELETE /foo in the swagger UI I'm good to go and definitely don't need to know what a foo is, what fields it has, what those mean, what happens when I PUT, what format I'm supposed to use for PATCH, and so on. You can develop a consistent and reasonable way to use HTTP verbs in your API, and if done well it can be helpful to consumers, but it's 4 bits of information max. It says very little and I will still need docs so I can learn what special qualities you have included that are definitely the right way to do things, unlike every other person who exposed something over HTTP and felt that verbs were very meaningful and important. They were morons who should be ignored.

Point to the part of my post where I said that a perfectly implemented RESTful api would make you not need documentation. A well-implemented API is documentation, much the same as well-written code. If your API is self-documenting, the amount of explicit documentation (comments, API docs) you actually need to read in order to comprehend it can be lessened significantly, which is Good because the more time I spend having to read your documentation the more cognitive complexity I'm adding and the less time I'm spending actually implementing.

Given:

GET /foo/27/bar

POST /getBarForFooWithId

{
id: 27
}

I sure as hell know which one I find easier to comprehend, and which one I'd want to develop against

Nomnom Cookie
Aug 30, 2009



ChickenWing posted:

Point to the part of my post where I said that a perfectly implemented RESTful api would make you not need documentation. A well-implemented API is documentation, much the same as well-written code. If your API is self-documenting, the amount of explicit documentation (comments, API docs) you actually need to read in order to comprehend it can be lessened significantly, which is Good because the more time I spend having to read your documentation the more cognitive complexity I'm adding and the less time I'm spending actually implementing.

Given:

GET /foo/27/bar

POST /getBarForFooWithId

{
id: 27
}

I sure as hell know which one I find easier to comprehend, and which one I'd want to develop against

I'm gonna go with the one that has better docs. A URI is not docs. At best it gives you the same level of information contained in method signatures, and it's still necessary to look at the docs and discover what's in those parameters, what will happen when I make a request, what the response will look like. Doing things RESTfully strongly encourages consistency in how you do this, which is very good and I agree that consistency is very helpful in being able to use an API without referring back to the docs every 30 seconds. However, that's far from the only way to do things and get a good result. REST is merely one way to get to the things that actually matter: docs, function, consistency, correctness.

Unless you are saying that it would actually be a struggle for you to figure out that you when you want to update a baz, the proper operation to look for would be something like POST /updateBazWithId instead of PUT /baz/27.

Rubellavator
Aug 16, 2007

Whatever you're doing write it in a stupid and obtuse way so that you'll have to document it.

Volguus
Mar 3, 2009

Kevin Mitnick P.E. posted:

I'm gonna go with the one that has better docs

Let me give you a hint: nobody ever reads the drat docs unless is the last resort (that is, nothing they've tried so far works). You can force internal developers to read your docs for your API, sure, an external developer would just laugh in your face. People like predictability, people like repetition, people like familiarity. Throw them head first in your twisted world and they'll run screaming. And absolutely nothing that your API provides is transferable knowledge and that's just a waste of everyone's time.

sunaurus
Feb 13, 2012

Oh great, another bookah.
Wow looks like there's a bunch of cool opinions on these last few pages, here are some actual facts though:

1) There is nothing wrong with RPC-style URLs (POST /do-complex-operation), anybody who tells you otherwise is dumb (and so is trying to turn complex procedures into resource-based urls for no loving reason other than deluding yourself into thinking you're doing REST)
2) REST is much more than just having resource-based URLs. REST-style collection-resource URLs are totally OK for simple apps, especially if you can put a lot of your business logic in whatever client will be using your API, but just because you have URLs like /things/1 does not mean you have a REST API.
3) Actual REST is not something that you need to be doing for an API that is consumed by a machine. HATEOAS is a stupid waste of time.
4) Using HTTP response codes as application error codes can be very bad. You get 404 from an API, what just happened? Did someone break their nginx configuration? Maybe there's a bug in their application url routing logic? Maybe they just changed their endpoint without telling anybody? Or is a resource actually missing from their database? There's no way to know! Sending a proper error code and (and possibly an error message) in the response body can give API users a lot more confidence in their assessment of what the gently caress is wrong.

Kevin Mitnick P.E. posted:

Things that matter, in order:

  1. Documentation
  2. Functionality
  3. Consistency
  4. Correctness

Things that don't matter:

  • URL structure
  • Signalling errors in the status code or response body
  • Content type
  • HTTP verbs lining up with semantics


Assuming the documentation is up to snuff, this is a good API.

This guy seems like a cool and pragmatic developer, everybody should try to be more like this guy.

sunaurus
Feb 13, 2012

Oh great, another bookah.

Volguus posted:

Let me give you a hint: nobody ever reads the drat docs unless is the last resort (that is, nothing they've tried so far works). You can force internal developers to read your docs for your API, sure, an external developer would just laugh in your face.

Well this is definitely one the strangest opinions I've encountered so far this year

Nomnom Cookie
Aug 30, 2009



Volguus posted:

Let me give you a hint: nobody ever reads the drat docs unless is the last resort (that is, nothing they've tried so far works). You can force internal developers to read your docs for your API, sure, an external developer would just laugh in your face. People like predictability, people like repetition, people like familiarity. Throw them head first in your twisted world and they'll run screaming. And absolutely nothing that your API provides is transferable knowledge and that's just a waste of everyone's time.

I am the external developer. I don't make APIs, I consume them. The only portable knowledge is how HTTP and JSON work. Using some random thing without docs is not possible. The very first wall you run into is auth. How are we doing it this time? Query param, Authorization header (Basic, most likely, but maybe something more fun like Bearer or Digest), not-Authorization header, OpenID, some bespoke flow? Once I'm over that hurdle, how am I supposed to know what endpoints are available? Even if hitting / gives me a list of endpoints, what am I supposed to do with that? What's your request and response schema? How do I search, how do I sort, how do I paginate? What is your search syntax, what fields can I sort on, what's the maximum page size?

Everyone does it differently. You're saying that consistency with how everyone does it is important, and it doesn't hurt, but there just isn't that much to be consistent with, overall. Internal consistency is far, far more important. When someone does finally come up with The Right Way To Do HTTP APIs, you bet I'll be on board and tell everyone to do everything that way, but we're not there yet. REST is a limited, significantly flawed approach that has mainly gotten traction by encouraging taxonomy fetishists to argue about the right way to make something that's actually useful and still has beautiful URLs. Just making something that works and makes sense is too easy. No one pays attention, no one remembers, it doesn't get mindshare.

Roll Fizzlebeef
Sep 9, 2003


I can admit that I care about making a nice URL scheme for an api mainly to satisfy my sense of aesthetics and desire for things to seem organized and logical. I am not ashamed.

Volguus
Mar 3, 2009

sunaurus posted:

Well this is definitely one the strangest opinions I've encountered so far this year

Unfortunately this opinion came from experience. I wrote them docs, them volumes, only for the dumbest questions to be sent to support or to find them on stackoverflow. Really, 5-minutes-with-the-docs questions. No, it's not funny and this is not a joke.

Kevin Mitnick P.E. posted:

I am the external developer. I don't make APIs, I consume them. The only portable knowledge is how HTTP and JSON work. Using some random thing without docs is not possible. The very first wall you run into is auth. How are we doing it this time? Query param, Authorization header (Basic, most likely, but maybe something more fun like Bearer or Digest), not-Authorization header, OpenID, some bespoke flow? Once I'm over that hurdle, how am I supposed to know what endpoints are available? Even if hitting / gives me a list of endpoints, what am I supposed to do with that? What's your request and response schema? How do I search, how do I sort, how do I paginate? What is your search syntax, what fields can I sort on, what's the maximum page size?

Everyone does it differently. You're saying that consistency with how everyone does it is important, and it doesn't hurt, but there just isn't that much to be consistent with, overall. Internal consistency is far, far more important. When someone does finally come up with The Right Way To Do HTTP APIs, you bet I'll be on board and tell everyone to do everything that way, but we're not there yet. REST is a limited, significantly flawed approach that has mainly gotten traction by encouraging taxonomy fetishists to argue about the right way to make something that's actually useful and still has beautiful URLs. Just making something that works and makes sense is too easy. No one pays attention, no one remembers, it doesn't get mindshare.

Exactly my point: "How are we doing this now?" . No, learning every which way just because the dev in charge was a moron is not fun, not fun at all. Just making something that works, however (and here I disagree with you), works without you even noticing. And that's the best feeling in the world: "It just works". I know of a very successful software & hardware company (named after a fruit) which made mediocre products but it based its entire marketing material on this one slogan: "It just works". This is what people want and developers are no different.

REST is far from perfect and it has severe limitations. However, doing a "POST GetShit" is fundamentally wrong. Philosophically, realistically, experimentally, wrong. Don't do that.

Bongo Bill
Jan 17, 2012

Please do document your crimes against sensible API design, however.

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

Roll Fizzlebeef posted:

I can admit that I care about making a nice URL scheme for an api mainly to satisfy my sense of aesthetics and desire for things to seem organized and logical. I am not ashamed.

:hai:

ErikTheRed
Mar 12, 2007

My name is Deckard Cain and I've come on out to greet ya, so sit your ass and listen or I'm gonna have to beat ya.
During sprint retro earlier this week I called out one of our devs for repeatedly going off on unrelated tangents. Basically he was verbalizing new tasks he had in his head, so I was like "hey this stuff isn't relevant to this meeting, can we table this and talk about it later?".

Today he comes up to me on his way out and says he doesn't like how I said it and to ask if next time I can ask him "can we take this offline?" instead. I don't really see how the garbage corporate speak is any different than what I said, but at least now I can say this every time I want him to shut the gently caress up.

Of course this is also the guy who clips his nails at his desk in our open office area.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
It's a simple thing, really: publicly praise, privately criticize, and punch them in the face when they clip their nails.

Xik
Mar 10, 2011

Dinosaur Gum

ErikTheRed posted:

Of course this is also the guy who clips his nails at his desk in our open office area.

Assert your dominance by grabbing the toe nail clippings and chewing on them while staring directly into his eyes.

sunaurus
Feb 13, 2012

Oh great, another bookah.

Volguus posted:

However, doing a "POST GetShit" is fundamentally wrong. Philosophically, realistically, experimentally, wrong. Don't do that.

You're absolutely wrong here. I think you're under the assumption that POST means "create", but it certainly doesn't. If you were to say "PUT GetShit" is fundamentally wrong, you would be right - PUT has a very strict semantic meaning in HTTP, it either replaces or creates something. It's different with POST - all POST means is that the server must process the request according to the specific rules of that endpoint. Nothing needs to be created on the server as a result. If you define an endpoint like /get-something, then it's perfectly valid to have that endpoint process a request like {id: 1} by returning an existing something with the id 1.

bob dobbs is dead
Oct 8, 2017

I love peeps
Nap Ghost

sunaurus posted:

You're absolutely wrong here. I think you're under the assumption that POST means "create", but it certainly doesn't. If you were to say "PUT GetShit" is fundamentally wrong, you would be right - PUT has a very strict semantic meaning in HTTP, it either replaces or creates something. It's different with POST - all POST means is that the server must process the request according to the specific rules of that endpoint. Nothing needs to be created on the server as a result. If you define an endpoint like /get-something, then it's perfectly valid to have that endpoint process a request like {id: 1} by returning an existing something with the id 1.

You need to be purged, unironically

Volguus
Mar 3, 2009

sunaurus posted:

You're absolutely wrong here. I think you're under the assumption that POST means "create", but it certainly doesn't. If you were to say "PUT GetShit" is fundamentally wrong, you would be right - PUT has a very strict semantic meaning in HTTP, it either replaces or creates something. It's different with POST - all POST means is that the server must process the request according to the specific rules of that endpoint. Nothing needs to be created on the server as a result. If you define an endpoint like /get-something, then it's perfectly valid to have that endpoint process a request like {id: 1} by returning an existing something with the id 1.

You are technically correct - the best kind of correct - you can do whatever you want in a POST request. Doesn't mean that you should. "POST GetShit" violates the semantics of your operation. There are cases in the design of an API where using POST to get data makes sense and sometimes is the only way. If you do that all the time (as our friends here seem to be doing) what you have is an RPC, so just go an use an RPC helper library. You get clear client-server contract specification, you can get code to be generated for you to make it easy to implement the details, there are a ton of benefits.
Not every HTTP server needs to provide a REST api. You come and say "I perform commands, that are not cacheable nor safe nor idempotent" that's perfectly fine. That's not REST though. JSON-RPC, SOAP, gRPC are all valid and established protocols. Use one.

Vulture Culture
Jul 14, 2003

I was never enjoying it. I only eat it for the nutrients.
but what if PUT GetShit replaces a function

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...
What if we didn't have different URIs at all, or verbs, just the one endpoint, no post body, and made different requests in the headers?

Think about it, no more arguments about what the one true uri scheme is, no question of how to serialise data in the post body, and the world's most tedious derail goes away.

Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS
What if we just stopped yak shaving like loving idiots and built something that worked and was well documented so others can use it

What a wonderful world that would be

sunaurus
Feb 13, 2012

Oh great, another bookah.
I'm actually extremely surprised at the amount of posters here thinking that half-assed REST is a good way of designing HTTP APIs. I feel like this discussion is starting to go in a circle, so let me just summarize what my point has been all along: REST does not equal HTTP. Claiming that all HTTP APIs must be built using REST semantics (not HTTP semantics) is just odd.
REST does not equal CRUD. HTTP verbs do not equal CRUD. Also, most real-world HTTP APIs are not just CRUD.

As someone who has had the pleasure of consuming a wide variety of HTTP APIs, I definitely agree with the posters saying that any type of API with consistent design and good documentation is awesome to use. I've also run into tons of half-assed REST APIs created by developers who have an incomplete understanding of REST (which I'm guessing they got from some blog or stack overflow or something), these have not been so fun to use.

From some of the posts I've seen here, I assume a bunch of you will remain unconvinced and keep thinking that HTTP verbs for CRUD + resource-based URLS (which is NOT enough to be REST anyway) is some sort of holy grail of API design. I guess that opinion will change at some point when people start blogging less about REST and more about whatever the next API fad will be, so I'm just going to stop posting about HTTP and REST.

sunaurus fucked around with this message at 17:34 on Apr 6, 2019

Ghost of Reagan Past
Oct 7, 2003

rock and roll fun
Your API should be consistent, sane, well documented, and easy to understand.

Insisting that it strictly implement some idealized REST structure or whatever is foolish, especially if it ends up making more sense -- as it often does -- to deviate. If it makes more sense for a data request to be a POST, make it a POST. If it makes more sense to use a different URL structure than some ideal, use it. Just build some poo poo in a reasonable way and only assholes will complain that your API isn't strictly RESTful by whatever loving notion they have in their head.

(note: we are all assholes in this industry)

2nd Rate Poster
Mar 25, 2004

i started a joke
The more "RESTful" APIs I deal with the more convinced I am that REST (or any non code defined service interface) is trash.

From the client end you end up re-implementing client code for every api you integrate with, because no dev team can agree to anything.

From the server end, most REST standards only get you so far, you'll need to make decisions on how filtering/sorting/paging gets implemented, and poor choices in those parts will haunt your team forever.

Yeah you can get around all this if your documentation and client code game is great, but at that point why not just publish a code enforcable service contract ala grpc/thrift and call it a day? Sure, you'll still needs docs on the WHYs of your API, but that is the most important piece! And with traditional REST services, the WHYs are often neglected because you have to sink so much time into documenting the HOWs.

I hope because of the above, we'll start to see a lot of services moving away from "RESTful" semantics, and towards something like grpc web. Which provides for a service contract but still allows you to keep HTTP if thats your thing.

2nd Rate Poster fucked around with this message at 23:37 on Apr 6, 2019

Adbot
ADBOT LOVES YOU

redleader
Aug 18, 2005

Engage according to operational parameters
It also helps that no one in the world who isn't Roy Fielding understands what REST actually is.

2nd Rate Poster posted:

Yeah you can get around all this if your documentation and client code game is great, but at that point why not just publish a code enforcable service contract ala grpc/thrift and call it a day? Sure, you'll still needs docs on the WHYs of your API, but that is the most important piece! And with traditional REST services, the WHYs are often neglected because you have to sink so much time into documenting the HOWs.

Something that SOAP mostly got right.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply