
One-to-one relationships and subresources in REST APIs - Peroni
http://developers.lyst.com/2015/02/20/1-to-1-relationships-and-subresources-in-rest-apis/
======
dyoder
A 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
So you want your user data chached and accessible by others?

~~~
tehwebguy
You can still use authentication

------
_jb
Interesting. 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
This 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.

------
jessaustin
_Do 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
PUT 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
TFA 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
fair 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/)

------
jalfresi
URLs 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
True, 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.

------
bjrnjs
I 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).

------
EGreg
I wish there was a standard way to do batch operations in REST though

~~~
bostond
There 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
I 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.

~~~
bostond
> I took a look through it, and it seems woefully inadequate for batching
> "get" requests together.

I must say I think that's quite by design. The semantics of a PATCH request is
to modify the given resource.

~~~
zkhalique
So what about batching GET requests?

------
ExpiredLink
Authorization to access resources is a big problem in REST. Round Four seems
to be an appropriate approach.

~~~
leeoniya
i 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.

~~~
rdeboo
Isn'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.

~~~
tankerdude
Putting 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.

~~~
leeoniya
well, you need authentication data in every request, which includes
GET/DELETE/HEAD/OPTIONS requests with no payload. so either you use query
strings (which suffers from the logging issue) or you use headers/cookies
which some people argue isn't "REST"ful.

