[HN Gopher] How to (and how not to) design REST APIs
___________________________________________________________________
How to (and how not to) design REST APIs
Author : stickfigure
Score : 95 points
Date : 2023-11-01 19:06 UTC (3 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| saikatsg wrote:
| Liked the idea of using wiki as blog
| bitwrangler wrote:
| he actually writes about that. I happen to like it too.
|
| https://github.com/stickfigure/blog/wiki/GitHub%27s-wiki-mak...
| nesarkvechnep wrote:
| Half of the points are complete bs. URLs don't matter in REST.
| What matters are link relations.
| 541 wrote:
| Care to elaborate briefly on why they do?
| lmz wrote:
| "REST" is supposed to be an architectural style reflecting
| the Web as used by humans. Humans don't normally manually
| construct URLs. They navigate based on links from an entry
| point. (See also: https://hypermedia.systems/hypermedia-
| components/#_self_desc... )
| tkiolp4 wrote:
| The vast majority of people using REST do not follow its
| original definition, so the original definition doesn't
| matter anymore.
|
| It's like human languages: REST is whatever we make of it,
| regardless of what academics say.
| thedougd wrote:
| HATEOAS adds that to REST.
| DrDroop wrote:
| I would go even further and say that REST is BS Most people
| understand REST as a format for URLs and a particular semantics
| for HTTP methods. While it can be perfectly ok to design an api
| like person?id=123. This is the way that Postgrest does it,
| which works, and makes certain things like entities with
| composite primary keys way easier.
|
| Other, like OP, think REST isn't going far enough in that
| HATEOAS is what "really" makes something restfull. This doesn't
| really work in practice as if changing the schema of some JSON
| response can magically change the behaviour of an application.
| I you want to lift all the logic to the server, I guess you can
| use htmx, but then you are not building an api anymore but a
| remote rendering engine.
| switch007 wrote:
| Some good points - particularly about not returning arrays (I've
| made that mistake!)
|
| But I feel 410 instead of 404 is pretty controversial:
|
| > There are many layers of software that can return 404 to a
| request
|
| Anything in your stack can return any HTTP error code - I don't
| see why 404 is special.
|
| > When calling (say) GET /things/{thing_id} for a thing that
| doesn't exist, the response should indicate that 1) the server
| understood your request, and 2) the thing wasn't found.
| Unfortunately, a 404 response does not guarantee #1.
|
| The server is free to return other codes for other classes of
| problems. The server could return 400 for a bad request, and
| leave 404 for "thing wasn't found", indicating it understood the
| request but it wasn't found.
|
| Also surprised not to see RFC 7807 / RFC 9457 (Problem Details)
| not mentioned in the "structured error format" section.
| theandrewbailey wrote:
| That rule is a hot take.
|
| > You could use 404 but return a custom error body and demand
| that clients check for a correct error body. This is asking for
| trouble from lazy client programmers. It might or might not be
| "your fault" when clients see eventually inconsistent data, but
| the support calls they send you will be real.
|
| Make sure that your 404 responses were always documented, then
| tell them to RTFM.
| stickfigure wrote:
| The problem is that the support call comes in as "your DELETE
| call isn't actually deleting". Sure it's not your fault, but
| it imposes a cost on you to investigate. And of course the
| first time you go directly to RTFM without checking will be
| the time it actually is your bug.
|
| 404 is special because it's so incredibly common. Why take
| the risk? There are other perfectly good error codes that -
| in practice - don't have this issue.
| DSMan195276 wrote:
| > Anything in your stack can return any HTTP error code - I
| don't see why 404 is special.
|
| I'm surprised you don't - in my experience 404's are by far the
| most common response to get when you haven't wired things up
| correctly. Sure anything in the stack _can_ return any code and
| response they want, but you're still much more unlikely to come
| across a 410 rather than 404. If that unlikeliness saves you
| support calls down the line then that's pretty good.
| layer8 wrote:
| With REST 404s due to missing resources (non-existing ID),
| you should generally get corresponding error information in
| the body (as also described in TFA), and clients should
| log/display that information. That should make enough of a
| difference. There's a lot of "should" here, of course, but
| instead of teaching developers to not use 404, it would be
| better to teach them to create and handle error responses
| appropriately.
| noiv wrote:
| I prefer to consider 404 as protocol error and missing thing as
| business error. That way 404 signals wrong endpoint and 200 +
| error message + empty result set signals wrong id.
|
| Or even more simple: Anything other than 200 means check
| infrastructure docs and if you don't like the 200 check the
| business requirements.
| stickfigure wrote:
| As a client I generally dislike APIs that use 200 for error
| conditions. The problem is that API implementors often change
| the structure of the response. GET
| /thing/THG123 # on success: {"id":"THG123",
| "name":"thingie"} # on failure: {"error":"no
| such thing"}
|
| Working in typed languages, this requires parsing the
| response, determining success or failure, then reparsing the
| response into the appropriate type. Annoying.
|
| Of course it's not always like that, some APIs will put both
| the error and data in a wrapper object and one field or the
| other will always be null: {
| "error": null, "result": {"id":"THG123",
| "name":"thingie"} }
|
| This is less annoying but it's still tedious. We could
| eliminate the wrapper if we only had an out-of-band signal to
| indicate whether the client should expect a success response
| or an error response... like maybe an HTTP status code? I
| mean, it's right there, why not use it?
| esafak wrote:
| > Some good points - particularly about not returning arrays.
|
| I don't get that one; why is an object with an array property
| more evolution friendly than an array of objects?
| layer8 wrote:
| Because you can add new properties for response-level global
| information on an object, but not on an array.
| esafak wrote:
| Obviously if it was global, but if not, you'd include it in
| the objects in the array, no? This is not a question of
| schema evolution per se.
| AlexandrB wrote:
| Found a contradiction that I don't understand. From rule 1:
| # GOOD GET /products # get all the products GET
| /products/{product_id} # get one product # BAD
| GET /product/{product_id}
|
| But then in Rule 2: GET
| /shop/{shop_id}/listings # normal, expected
|
| Shouldn't that be "/shops/{shop_id}/listings"? Or is it plural
| only if you can actually GET the path (i.e. there's no GET for
| just "/shop") and otherwise it should be singular?
| stickfigure wrote:
| This is the Etsy API, but actually was a typo on my part. They
| use the plural /shops (as I showed in the other Etsy example).
| I've corrected the original article, sorry about that!
| robertlagrant wrote:
| Plural or singular seems far too marginal to be good or bad. I
| use singular.
| iterati wrote:
| Same. My table names are also singular.
| prisonality wrote:
| I use singular too, but I always wonder to those sticking
| with plural - what's the convention for words which plural
| and singular are the same.
|
| ie - like 'staff' or 'species' or 'aircraft'.
|
| Then I can add suffix to those singular ie - 'staffList',
| 'speciesList' etc
| teaearlgraycold wrote:
| Regarding #8 - just do not use http status codes for application
| errors. They are for routers, caches and proxies. Your
| application should pretty much only return 200 even on errors.
|
| Edit: Bring on the downvotes. I will die on this hill.
| hooverd wrote:
| I see SOAP has entered the chat.
| pskinner wrote:
| *graphql
| throw_m239339 wrote:
| > Regarding #8 - just do not use http status codes for
| application errors. They are for routers, caches and proxies.
| Your application should pretty much only return 200 even on
| errors.
|
| What is an application error? If a user tries to query a
| ressource they are not authorized access to, then returning a
| 401 is appropriate, if the resource doesn't exist then 404 is
| also appropriate, in theory (maybe not in practice for security
| reasons but whatever). Nothing wrong with that.
|
| HTTP codes are not made only for routers, caches and proxies,
| HTTP was made for user agents such as browsers, HTTP is one of
| the foundations of REST.
|
| and I didn't downvote you, I'm just asking a question.
| teaearlgraycold wrote:
| To be fair I was being a tiny bit inflammatory. I think it's
| appropriate to use HTTP codes sparingly. Personally I'll use
| 401 and 500 but everything else is 200. And if the API is
| meant for public consumption by 3rd party devs then meeting
| expectations is more important than my personal philosophy.
|
| But basically the overlap between the classic HTTP status
| codes and your API's functionality is IMO coincidence. Unless
| you're building a BLOB store or HTTP middleware you probably
| do not have enough overlap for it to be truly appropriate for
| your domain. HTTP is the envelope. It doesn't need to mix
| with your custom JSON API.
| pie_flavor wrote:
| I don't know why you're being downvoted. I think you're
| completely wrong, but it's not like you're being rude about it.
|
| Status codes are not necessarily useful for the developer
| _directly_ , as they're a second channel for the same
| information, but they are useful for middleware of all kinds
| (your argument applies equally to browsers showing errors to
| users, and the same counterarguments apply to programmers). For
| example, the HTTP library I'm using has an error_for_status
| function which conveniently raises a runtime error, without me
| having to dig into the response to do that manually. Also, if
| you invent more kinds of errors later, or even if you just
| haven't published a master table of errors where I can see it,
| the status code will still let me extract useful semantic
| information out of an error kind my code has not been written
| explicitly to handle.
| aero142 wrote:
| Doing REST microservices is incredibly slow because of the amount
| of work it is to agree on what a "clean" and "consistent" api
| looks like for each service. It's just such an endless well of
| trying to establish best practices without refactoring
| constantly.
|
| It's worth it for your public API, but it's such a huge time sink
| for internal APIs.
| wargames wrote:
| I would be interested in what you are using internally that is
| allowing you to move quicker.
| elevation wrote:
| Rule #1 is terrible advice.
|
| Avoid plural nouns in English API endpoints because English is
| full of irregular plurals. For example:
|
| goose -> geese child -> children index -> indices vertex ->
| vertexes analysis -> analyses
|
| This makes English plurals unpredictable especially for for non-
| native speakers and hurts API consistency and discoverability.
|
| Also consider that for a CRUD interface you may need the singular
| form anyway (POST api/student/create), and adding the plural
| means doubling the API route namespace.
|
| It's cleaner and simpler to stick with singular nouns.
| marcellus23 wrote:
| > for a CRUD interface you may need the singular form anyway
| (POST api/student/create)
|
| Why? What's wrong with api/students/create?
|
| > Avoid plural nouns in English API endpoints because English
| is full of irregular plurals.
|
| I don't buy this. I mean, yes, it's true, but how often do
| people really need to write these endpoints after initially
| writing the client code?
| stickfigure wrote:
| You use plurals anyway to fetch collections:
| GET /students
|
| So you can't escape the problem unless you want `GET /child` to
| fetch multiple children.
|
| Also, you should avoid verbs in URLs (IMHO, of course). You're
| adding to the students collection, so post to students:
| # BAD POST /student/create # GOOD
| POST /students
| pavlov wrote:
| Does "GET /students" return all the students in the system?
| Probably not.
|
| So in fact you're fetching some subset of students anyway,
| and the size of the returned set might be one or zero
| depending on your query.
|
| Given that, "GET /student" seems just as meaningful because
| neither the singular nor the plural can fix the ambiguity
| about what you're actually getting.
| stickfigure wrote:
| Yes, I would expect GET /students to return all of the
| students (or at least, all of the students visible to me).
| Typically with query parameters for filtering:
| GET /students?min_age=20
|
| Alternatively, `students` might be a collection attribute
| on another resource: GET
| /classes/{class_id}/students
| zdragnar wrote:
| I expect singular to return one, and plural to return a
| set, which could range from 0...n.
|
| Likewise, I wouldn't expect a singular to return a single
| object wrapped in an array, but I would always expect
| "/plural" (with no further qualifier in the url) to return
| an array, regardless of 0, 1 or more results.
|
| Why would returning a full set be a condition of whether or
| not plural is ambiguous?
| bonzini wrote:
| "POST /students" is a create action, but verbs are fine for
| individual entities, for example "POST /students/ID/enroll".
| 3cats-in-a-coat wrote:
| An API is not an essay, in OOP you write Array<Student> and
| not Array<Students> and yet you understand the type is about
| an array of students. Getting hung up on grammar in an API is
| probably the dumbest problem to have.
|
| If you think `GET /student` is confusing, or more
| importantly, structurally restrictive as an API, you can
| think about it as `GET /student/filter` where the "filter"
| may be a specific student id, or a range of ids, or other
| conditions such as `GET /student/top` or `GET
| /student/graduated` and then all students will be just the
| filter "all" or: `GET /student/all`.
|
| As for `POST /student/create`... it doesn't matter. To use
| one of Fielding's own examples from his blog, how'd you turn
| a lamp on and off via REST? Would you be like `POST /lamp`?
| No. It's unclear WTF is happening.
| hnbad wrote:
| > Fielding's own examples from his blog, how'd you turn a
| lamp on and off via REST? Would you be like `POST /lamp`?
| No. It's unclear WTF is happening.
|
| No, of course you'd be like `PATCH {"light": "off"} /lamp`!
|
| Kidding of course but it's true that REST purity does not
| make for intuitive APIs in complex real-world problem
| domains.
| jordanrobinson wrote:
| While I do agree with this in almost all cases, I have found
| scenarios where there are actions that don't map easily to a
| HTTP verb and need something more explicit.
|
| What I've generally done in these cases is pretty similar to
| https://cloud.google.com/apis/design/custom_methods which
| also explains the problem better than I can.
|
| I'd be interested as to how you'd solve some of these
| problems without an explicit verb in the path.
| stickfigure wrote:
| I'm not a purist; for unusual edge cases, I'll put a verb
| (or something appropriate to the context) at the end of the
| path. But `create` isn't unusual, just POST to a
| collection.
| prisonality wrote:
| how do you differentiate between plural vs singular of:
|
| `GET /staff`
|
| ?
| stickfigure wrote:
| I don't? It's fine. I'm also fine just adding an 's' to
| many words that have unusual plurals; English is flexible,
| and "persons" is a perfectly acceptable substitute for
| "people".
|
| That said, I don't love your example. Staff does have a
| plural, staffs - as in, the separate staffs of multiple
| organizations.
| prisonality wrote:
| what's your opinion of using suffix like '_list' to
| differentiate it ?
|
| ie:
|
| GET /species
|
| and
|
| GET /species_list
|
| ?
| takinola wrote:
| You really should not include the action in the URL ie rather
| than
|
| GET api/student
|
| POST api/student/create
|
| DELETE api/student
|
| it should be
|
| POST api/students
|
| GET api/students
|
| DELETE api/students
| golergka wrote:
| It gets even more unpredictable for everyone involved when it's
| a non-native speaker who writes the API schema.
| sigmonsays wrote:
| are we beating a dead horse here?
|
| Havn't we talked about building REST APIs enough yet?
| n42 wrote:
| unequivocally
| RedShift1 wrote:
| Hello there. Have you heard of our lord and savior, GraphQL?
| HatchedLake721 wrote:
| There's a new generation that didn't bikeshed about singular or
| plural nouns in the API endpoints. Let them be?
| physicsguy wrote:
| I'd add:
|
| * If you're going to forbid people changing a parameter with a
| PUT or PATCH request, then the schema for these shouldn't list
| them as parameters. This seems to creep in to APIs constantly as
| people are lazy and will use the same serializer method as for
| POST with an additional check somewhere in the code that changes
| the response. Just don't do it!
|
| * Don't change the response format based on query parameters. It
| makes it hard for typed languages to use the API because the
| client has to handle all of the weird response types you've got.
| Inevitably you end up with more and more getting added and it any
| client becomes crazily complicated. 99% of the time it's not
| worth the bandwidth saving - and if there's lots of useless
| information that clients don't want, it's worth thinking about
| whether the API design is right in the first place.
|
| * Stick to one mechanism for doing things. Pagination and sorting
| behaviour should be the same for all endpoints. The end user
| doesn't care that you're a hip microservices company where teams
| don't talk to each other - if the APIs behave weirdly and
| inconsistently between themselves, it will be hard to use.
| janfoeh wrote:
| I very much agree with your first and third point, from
| experience. As for the second one -- if consuming dynamic data
| structures is hard in typed languages, maybe they are not the
| right tool for that particular job?
|
| What I have seen is endpoints trying to corral their responses
| into one-size-fits-all schemas in the situation you're
| describing, with predictable outcomes. Lots of overhead in most
| situations, tricky documentation, lots of optionals.
|
| Under that premise, I have to say that at least for generic
| APIs with many differing clients, the idiosyncrasies of typed-
| language clients would not rank too highly on my list of design
| considerations -- not when they are in the way of simpler,
| easier to understand responses.
| Joker_vD wrote:
| As for the second point, that's what Accept header is for.
| And I personally never had much trouble in Go with
| deserializing all those "weird response types" but it may
| depend on one's coding style.
|
| > I have to say that at least for generic APIs with many
| differing clients, the idiosyncrasies of typed-language
| clients would not rank too highly on my list of design
| considerations
|
| Hey, would you like to consume an exchange format that has
| meaningful distinction between strings and atoms? Those come
| from the dynamically-typed languages area!
| corytheboyd wrote:
| It all turns into RPC anyway, I just can't care that much about
| REST anymore
| diarrhea wrote:
| Experienced point 6 with the GitHub API. "Repository" is a core
| Git(Hub) primitive, and across the entire API surface (they have
| an OpenAPI spec, 40 MB in size total), last I counted it was 48
| different versions of repository. For example, what's considered
| a repo owned by a user might be different from that of an
| organisation. There is no sane recourse but automatic code
| generation, which is a ton of effort in itself (tooling isn't
| great).
| gensym wrote:
| > REST APIs
|
| "You keep using that word. I do not think it means what you think
| it means".
|
| https://ics.uci.edu/~fielding/pubs/dissertation/top.htm
| n42 wrote:
| I feel like at this point I have heard convincing arguments for
| and against basically every point in this article, every article
| like it, and every comment on them.
|
| Hot take: it doesn't matter. If the user cared enough about your
| decisions to file a bug report or a complaint, you're doing
| something right. Consider that a success.
|
| Stop trying to shoehorn a creative outlet into your day job. Pick
| someone else's terrible design and stick to it.
|
| Frankly I am shocked to see an article on REST design on HN in
| 2023. We sort of figured this one out.
| fsaintjacques wrote:
| I highly recommend anyone to read Google's
| [AIP](https://google.aip.dev/). There's even a grpc schema linter
| for it. Put more focus on the resource data design than
| nitpicking on transport details. I would consider the best
| lessons to be:
|
| - Optional but supported user defined identifiers, it's so
| frustrating to work with API that passes you back an identifier.
|
| - String identifier (names) for resources, with some kind of type
| namespacing, i.e. the prefix in the author's document -
| Consistent set of fields (create_time, update_time, annotations,
| ...)
|
| - Avoid dynamic map (this is a JSON self-inflicted wound)
| aleksiy123 wrote:
| Second this. Reading this while working at google made me
| better design. Some that stand out to me are.
|
| Resource Oriented Design: https://google.aip.dev/121
|
| Declarative Friendly APIs: https://google.aip.dev/128
|
| Declarative friendly makes writing scripts, pipelines so much
| better because of idempotency. It also pairs very naturally
| with resource Oriented design.
|
| Long Running Operations: https://google.aip.dev/151
|
| LROs are applicable to any request that runs longer than a
| second or a couple of seconds. Having a unified interface can
| be very powerful for implementing offline task workers and
| pipelines.
|
| Filtering: https://google.aip.dev/160
|
| This one is probably controversial as it's makes implementing
| basic filtering quite a bit harder. I haven't quite seen the
| issues it's supposed to solve play out in practice but it's
| interesting nonetheless.
| 3cats-in-a-coat wrote:
| We need to forget this word REST, because all advice about it is
| superlame, regardless of the original paper.
| alxmng wrote:
| "RESTful" API design is mostly bike-shedding.
|
| There's no standard. Every REST API looks different. Clients have
| to refer to documentation anyway, so consistent URL patterns
| achieve nothing. People waste large amounts of time over totally
| inconsequential minutiae like whether to use singular or plural
| words in URLs.
|
| Separating idempotent calls from non-idempotent calls is useful,
| but REST overcomplicates this. All that's needed is read and
| write calls, yet REST has get, post, patch, put, delete...
|
| REST is also inefficient. Clients could read the data they need
| in one HTTP request, but most "RESTful" APIs force clients to
| make many requests for the sake of what is essentially
| aesthetics.
| tkiolp4 wrote:
| Agree. But I pick REST (or "json over http") any day of the
| week instead of graphql, soap, grpc, etc.
| nine_zeros wrote:
| Graphql just for the sake of graphql is a disaster for
| backend engineers.
| waynesonfire wrote:
| What's your view on this,
|
| https://news.ycombinator.com/item?id=38103310#38104983
|
| ?
| charlus wrote:
| Rule #11, and the general text there on idempotence was very
| interesting and I definitely learnt nicer ways of handling this,
| thank you.
| postalrat wrote:
| A missing rule is "DON'T use strings for timestamps". Which
| implies "Rule #6: DO use strings for all identifiers" is not good
| advice.
| jmull wrote:
| There are a bunch of bad rules here...
|
| Rule 1 - "DO use plural nouns for collections" - is an entirely
| arbitrary opinion.
|
| Rule 2 - "DON'T add unnecessary path segments" - I agree with the
| rule, but the examples are bad because, e.g.,
| "/listings/{listing_id} " and
| "/shop/{shop_id}/listings/{listing_id}" mean two different things
| (or at least they should). Now,
| "/shop/{shop_id}/listings/{listing_id}" is a complex path, so if
| your API doesn't need it, then I agree, don't include it. But if
| it does, then it would be bad to not include it.
|
| Rule 3 - "DON'T add .json or other extensions to the url" I
| mostly agree with the rule, but on the grounds of keeping things
| simple. Here, keeping to the standard (which means using Accept).
| But things like supporting a ".json" suffix are nice for cases
| where you want to give people (not programs) access to the
| different representations (should be in addition to Accept).
|
| This justification for rule 3: "URLs are resource identifiers..."
| is simply not true, at least for any reasonably useful definition
| of identifier. A URL points at a resource, that's it.
|
| Rule 4 is good. ("Rule #4: DON'T return arrays as top level
| responses") You want to keep the door open to adding metadata in
| the response body that will be very easy for clients to accept in
| a backwards-compatible manner.
|
| Rule 5 "DON'T return map structures" doesn't really make sense.
| Now, you shouldn't do it just to provide a lookup index -- the id
| should really be the inherent id of the data -- but it's a
| logically valid way to structure data and your API should strive
| to match the logical structure of the data. Also, the arguments
| here are not great.. e.g., "Converting an array of objects to a
| map is a one-liner in most languages"... that's true, but so is
| the converse. The openapi example doesn't make sense either.
| openapi v4 _could_ have simply added a "name" property to the
| object in the v3 structure, right next to the "post" property --
| just like the hypothetical list-based API. I would assume openapi
| has other reasons for the restructure, because the map-based API
| doesn't force it.
|
| Well, I'll stop there. It's not all bad, but just don't take
| these rules to the bank.
|
| Wait one more: Rule 8 "DON'T use 404 to indicate not found"
|
| Come on now, why even write something like that?
|
| The rule is more like, don't use 404 poorly. DELETE should be
| idempotent (that's a good rule), which means an attempt to DELETE
| something that could exist but doesn't happen to exist right now,
| isn't an error, and should return a 2xx code. 404 response for an
| attempt to delete on a route that doesn't exists makes sense
| (well, I guess unless your API is so dynamic that routes can be
| created and deleted on the fly, in which case even there you'd
| return a success code).
| jameshart wrote:
| This falls down as soon as it makes a fundamental
| misunderstanding of what makes a REST api into a REST api.
|
| It gives this as a 'bad' example: GET
| /v3/application/shops/{shop_id}/listings/{listing_id}/properties
|
| With the justification that "The {listing_id} is globally unique;
| there's no reason for {shop_id} to be part of the URL. "
|
| No the point of the API is that
| /v3/application/shops/{shop_id}/listings/{listing_id}/properties
| is a globally unique identifier. Your belief that parts of that
| id have global meaning outside the context of that identifier is
| irrelevant - that _path_ is the identifier for the resource.
|
| And having hierarchical paths is useful because you can do things
| like manage permissions on parts of the hierarchy - users might
| have permission to check listings in certain shops and we can
| characterize that as them having permission on
| /v3/application/shops/{shop_id}/listings/*.
|
| Directory structures of resource identifiers are good and logical
| and not a 'bad' API design practice at all. You might as well
| argue the UNIX file system is a bad design because all the files
| have a unique inode id so paths are completely unnecessary.
| stickfigure wrote:
| You apparently have not actually used Etsy's API.
|
| No, the shop id is _not_ in fact part of the globally unique
| identifier of an Etsy listing, and the properties are not
| dependent on the shop. Etsy listings have a 1:N relationship
| with Etsy shops.
|
| The API was a mistake, which they are slowly correcting -
| they've already changed: GET
| /v3/application/shops/{shop_id}/listings/{listing_id}
|
| to: GET /v3/application/listings/{listing_id}
|
| ...and I presume they will eventually change the rest of the
| listing-related endpoints over time.
|
| Managing permissions using the hierarchy of a URL is silly at
| best, dangerous at worst. The first thing any attacker will do
| is plug in an alternative shop id and see if it grants access
| to the non-permitted listing. If permissions are attached to
| the shop (and for Etsy, they are) the server needs to load the
| listing, figure out the associated shop, and then check
| permissions. The client cannot be trusted to provide the
| correct shop id, so there's no point in asking for it.
| sndsgd wrote:
| Regarding #2, I'm guessing the listings are sharded by shop_id,
| so without it you'll need to query all database shards.
|
| Is there a better place to include the sharding key in a REST
| request?
| henning wrote:
| Telling someone you should not return 404 for not found is a
| great way to not get hired at most tech companies.
| waynesonfire wrote:
| Regarding #9 BE consistent: this is the consequence of allowing
| chaos to take over. There are far fewer individuals trying to
| reduce complexity compared to those who are adding to it. And,
| the effort required to resolve these inconsistencies is 10x than
| that needed to create them.
| waynesonfire wrote:
| The author makes a good point about not throwing 404s.. a logical
| extension of this is that it should apply to all the other error
| codes. Does REST encourage the use of http error codes?
| layer8 wrote:
| Regarding rule #4 (DON'T return arrays as top level responses), I
| feel that meta information returned about the collection really
| fits the responsibility of HTTP headers. This is similar to
| existing response headers like Content-Length and Content-Range.
| REST clients already work with "out-of-band" information like
| HTTP statuses and e.g. If-Modified-Since. Do we always have add
| yet another layer to nest meta information in?
| hoherd wrote:
| While you may be right about headers, I think the point the
| article makes about easily adding more fields to the result
| without breaking backwards compatibility is pretty compelling.
| layer8 wrote:
| It's a good rule for non-collection resources and for the
| _elements_ of collection resources, but I was specifically
| thinking about collections, where all top-level information
| (apart from the elements of the collection themselves) is
| necessarily meta information about the returned data, and not
| part of the returned data proper.
| waynesonfire wrote:
| I struggle with this concept with RabbitMQ as well. The AMQP
| 0-9-1 protocol used by RabbitMQ has a headers table at the
| protocol level for user-defined key-value pairs that can be
| associated with the message payload. The same question applies
| here, what should go in this protocol header table vs on the
| message.
|
| One concern I have about using these user-defined headers is
| that in my designs I'll typically remove the payload from the
| AMQP envelope and propogate just the payload to the business
| logic. If the headers need to be included along with the
| business logic, there is the issue of propagating them. It
| seems risky to use the headers at the protocol level.
|
| Any thoughts?
___________________________________________________________________
(page generated 2023-11-01 23:01 UTC)