5 ms·
One-to-one relationships and subresources in REST APIs
- jalfresi 12y agoURLs are opaque in REST. This is an awful lot of article about URL design that doesn't matter (or is changeable at a later date). Remember, HATEOS means you can punt on decisions like this until later, and that's a cool thing!
- icebraining 12y agoTrue, though Round Four introduces an exception to that; URLs may be opaque, but the decision to use a single URL to represent everyone's carts is still relevant, since people will rely on it staying stable, regardless of how it looks.
- ExpiredLink 12y agoAuthorization to access resources is a big problem in REST. Round Four seems to be an appropriate approach.
- leeoniya 12y agoi think round 4 should have been the way to go from the beginning. a cart is not a sub-resource of the user. the user is just the auth-context for accessing the cart resource. it could be implicit and held by a cookie/session or token passed as a query param. to get a specific other user's cart, you would query GET /users/<user_id>/carts and then a follow-up GET directly to the cart resource regarding authorization, just pass a session token in the query string if you're against implicit headers/cookies.
- ExpiredLink 12y agoYou need to check all user authorizations for all resources. A potential n x m problem. The proposed solution means that you never give a 'user id' to the outside world. In REST parlance, a user isn't a resource.
- leeoniya 12y ago> In REST parlance, a user isn't a resource. this is not necessarily true. if you're managing users, then they are resources like anything else. but users can also act as contexts for operations and access, including auth/prmissions, audit/logging. when the user is acting as a context, it should be implicit and stored in a session, with an initialized token after login.
- ExpiredLink 12y agoIs REST context an 'official name'?
- leeoniya 12y agono, it's probably anti-REST anyhow. http://stackoverflow.com/questions/6068113/do-sessions-really-violate-restfulness http://stackoverflow.com/questions/6068113/do-sessions-reall... though your sessions do maintain some server context. you cannot let the client decide when to expire a session, for example. pure REST is a pipe dream. there are many things that work sub-optimally if adhering to strict rest as it pertains to http. see the second answer in that thread.
- rdeboo 12y agoIsn't passing the session token in the query string insecure? The payload of the requests will be encrypted (assuming HTTPS), but the urls are not. So I think you're opening the door to session hijacking in this way. edit: I was wrong about this. The URL will be confidential in transit. Thanks for setting me straight. I still think it is not a great design, but for different reasons: the url will be visible in your browser history and on the server side in the logs.
- leeoniya 12y agoeverything over HTTPS is encrypted except the ip addresses and port #. hostname is also encrypted (cause it's a header), though your insecure DNS pre-queries will give that away to anyone listening on the wire.
- icebraining 12y agoHostname is not encrypted if you're using SNI[1], and if you're not, you can only connect to IPs that serve a single HTTPS site, so it's not meaningfully hidden anyway. [1] http://en.wikipedia.org/wiki/Server_Name_Indication http://en.wikipedia.org/wiki/Server_Name_Indication
- leeoniya 12y agoah yes, forgot about that :)
- batbomb 12y agoI don't think you understand HTTPS. The URLs are, in fact, encrypted. That's why it's called TLS.
- tankerdude 12y agoPutting keys in query strings does leak information on the server though. Query strings are usually logged with the request in log files so you have to be sure to filter out the specific query string for the session token. That's the security concern that I see, especially if the logs get sent out somewhere/someone else for analysis.
- deleted 12y ago[deleted]
- EGreg 12y agoI wish there was a standard way to do batch operations in REST though
- bostond 12y agoThere is a proposal for such a standard for json document APIs: https://tools.ietf.org/html/rfc6902 https://tools.ietf.org/html/rfc6902 I'm not sure where this stands in the standards track.
- zkhalique 12y agoI took a look through it, and it seems woefully inadequate for batching "get" requests together. Say I want to get 90 disparate items, shouldn't I be able to batch those into one or two requests? On the server, I may have some cache in the script so I don't have to re-request the same items 90 times. For example I want to get 40 rooms, and for 20 of them, I want to get up to 20 participants in the rooms. My JS code shouldn't have to care about the batching. It should just send out batched requests, and the callbacks should be called. On the client side, we have this: http://platform.qbix.com/guide/patterns http://platform.qbix.com/guide/patterns -- see Q.batcher.factory But on the server side, we've had to implement our own format to get that implemented.
- timblair 12y agoJSON API [1] is an attempt to standardise the request and response formats for JSON APIs, and it supports an extension which permits multiple operations in a single request [2]. Facebook have their own, similar method of supporting batched calls through the Graph API [3], and this even permits you to specify dependencies between operations in a single request using JSONPath [4]. [1] http://jsonapi.org/ http://jsonapi.org/ [2] http://jsonapi.org/extensions/bulk/ http://jsonapi.org/extensions/bulk/ [3] https://developers.facebook.com/docs/graph-api/making-multiple-requests https://developers.facebook.com/docs/graph-api/making-multip... [4] https://code.google.com/p/jsonpath/ https://code.google.com/p/jsonpath/
- jessaustin 12y agoDo I really need to be able to update the Cart? Sure, but what do I need to update? Because I need to be able to add new items to it. However, that should be under the Item resource surely? Great! Now we can get rid of that too. My first thought was that POSTing to the cart (or the user) is the most obvious way to add items? But then I thought maybe you just PUT to /api/cart/item_number? That would be cool.
- leeoniya 12y agoPUT is almost always the wrong way to go, since it requires a complete replacement of the target resource, meaning your browser needs to know the entire structure. to add new items you would POST to /carts/<cid>/items. to update an item you would PATCH to /carts/<cid>/items/<iid> with qty=3 or some other partial attribute update what I do for my carts is PATCH to /carts/<cid>/items to partial mass-update all items with items[iid][qty]=x
- jessaustin 12y agoTFA already explains why carts don't need an id: for this application there is only one cart per account, and users only ever see their own accounts. The representation I was imagining being PUT would be an integer, like "1" or "5". The /api/cart/item_number resource could allow only the PUT and DELETE verbs, and /api/cart/ would handle GET. item_number, in this case, identifies an item that is for sale (EDIT: a SKU), not an association between such an item and a cart. EDIT: Keeping an integer at /cart/sku is the only association we need. /catalog/sku holds price and other associated values. /api/cart/ holds taxes, discounts, and whatnot. EDIT: It's as if you're arguing based on some theory you've read rather than on what we're discussing.
- leeoniya 12y agofair enough on the single-cart bit. however, when you do PUT, you leave it up to the client to choose the destination id (if it is not already known), this is not good. You should add items by POSTing to an item factory such as /cart/items. The cart will create the item(s) for you and that item resource will almost certainly hold additional data that was not passed in from the client (usually just SKU + qty) such as base price, calculated discounts, tax, etc. a PUT would not be appropriate as it requires the entire resource to be replaced (or created) at the destination specified by the client. the client rarely knows the entire resource (or has the permission to modify it at will), so follow-up updates should be done via PATCH /cart/items/<iid> or (mass) PATCH /cart/items http://restcookbook.com/HTTP%20Methods/put-vs-post/ http://restcookbook.com/HTTP%20Methods/put-vs-post/
- bjrnjs 12y agoI would've thought of it this way; Is the user bringing a cart (/user/<USER_ID>/cart/<CART_ID>)? Is he bringing his own cart (/user/<USER_ID>/cart)? Is the store supplying a cart for the user (/cart)? Applying real world objects and thinking, makes more sense in my mind. The third option instinctively is the most suitable way to go (IMO).
- _jb 12y agoInteresting. I normally try to stay away from the "logged in context" when I'm defining API endpoints since it limits what can be done with the API. I try to define the API for data, and let the consumers decide which data they want to show, as long as they can access this data. For instance, it could make sense for admin users to see other user's cart, but this design makes it impossible. I would normally go for something like `/cart?user_id={{id}}`, forcing API consumers to pass in the `user_id` (possibly reluctantly defaulting the value to `current_user_id` for convenience.)
- Zikes 12y agoThis design doesn't necessarily make it impossible, but it requires a little redundancy. An /admin/ set of paths could cover the administrative needs, including viewing users' carts.
- dyoder 12y agoA URL is an identifier for a resource. Everyone now has the same URL (identifier) for their shopping cart. If you're goal is to use HTTP effectively, this is bad. For example, it breaks HTTP caching. In effect, you have a variant of the RPC pattern that you say you're trying to avoid.
- ExpiredLink 12y agoSo you want your user data chached and accessible by others?
- deleted 12y ago[deleted]
- tehwebguy 12y agoYou can still use authentication