2

HTTP cookies violate the REST architectural style because they are independent of application state and they have no semantics, according to Roy Fielding’s doctoral dissertation Architectural Styles and the Design of Network-Based Software Architectures, § 6.3.4.2 ‘Cookies’:

An example of where an inappropriate extension has been made to the protocol to support features that contradict the desired properties of the generic interface is the introduction of site-wide state information in the form of HTTP cookies. Cookie interaction fails to match REST's model of application state, often resulting in confusion for the typical browser application.

Cookies also violate REST because they allow data to be passed without sufficiently identifying its semantics, thus becoming a concern for both security and privacy. The combination of cookies with the Referer [sic] header field makes it possible to track a user as they browse between sites.

So he suggests the following alternative:

As a result, cookie-based applications on the Web will never be reliable. The same functionality should have been accomplished via anonymous authentication and true client-side state. A state mechanism that involves preferences can be more efficiently implemented using judicious use of context-setting URI rather than cookies, where judicious means one URI per state rather than an unbounded number of URI due to the embedding of a user-id. Likewise, the use of cookies to identify a user-specific "shopping basket" within a server-side database could be more efficiently implemented by defining the semantics of shopping items within the hypermedia data formats, allowing the user agent to select and store those items within their own client-side shopping basket, complete with a URI to be used for check-out when the client is ready to purchase.

My understanding of his user preference example is the following. Let’s say that a website allows its users to choose between a light theme (the default) and a dark theme in a preference page at URI /preferences (like Stack Overflow). When a user chooses the dark theme, he should be redirected to the URI /preferences?theme=dark whose HTML representation will be the same as the HTML representation of the URI /preferences, except that it will be now in dark mode and the query ?theme=dark will be appended to all the embedded hyperlinks. That way, if the user selects for instance the embedded hyperlink to the home page at URI /home?theme=dark (not /home), then the HTML representation of the home page will also be in dark mode and the query ?theme=dark will also be appended to all its embedded hyperlinks. To revert to the light theme, then the user selects the embedded hyperlink to the preference page at URI /preferences?theme=dark, chooses the light theme in the preference page and should be redirected to the URI /preferences whose HTML representation will be the same as the HTML representation of the URI /preferences?theme=dark, except that it will be now in light mode and the query ?theme=dark will be removed from all the embedded hyperlinks. Is it what Roy Fielding meant?

Likewise for his shopping cart example, when the user adds a product i to cart, he should be redirected to a URI with a query ?product-{i}={product-i}&quantity-{i}={quantity-i} whose HTML representation will have that query appended to all its embedded hyperlinks. That way, when the user selects the check out hyperlink /checkout?product-1={product-1}&quantity-1={quantity-1}&…&product-n={product-n}&quantity-n={quantity-n}, the content of the shopping cart is sent to the website. Is it what Roy Fielding meant?

Géry Ogam
  • 6,336
  • 4
  • 38
  • 67
  • I haven't read Fielding's dissertation, and I don't follow the line of reasoning in those quotes, but since you asked me (out of band) to look at this question, I'd say that something like a theme sounds to me like two different *representations*, like, say, JSON vs XML in a machine-readable API. Those are typically handled with HTTP's content-negotiation protocol, rather than different URLs. After all, they're two different representations of the same resource. – Mark Seemann May 23 '21 at 20:51
  • @MarkSeemann Thanks for the feedback. The problem with [content negotiation](https://en.wikipedia.org/wiki/Content_negotiation) is that the user has no control over it in the web browser. And how do you persist the user choice in subsequent web pages with content negotiation? – Géry Ogam May 23 '21 at 21:12
  • I'm not sure I follow. REST is a design philosophy for machine-readable APIs. They aren't supposed to be consumed by a browser. For instance, you can't do `PUT` or `DELETE` requests with a browser. – Mark Seemann May 23 '21 at 22:04
  • @MarkSeemann REST is actually not restricted to machine-readable APIs: ‘More important to me is that the same design reflects good human-Web design, and thus we can design the protocols to support both machine and human-driven applications by following the same architectural style.’, ‘All it needs to know is the meaning of those instructions and some idea of what it wants to do next, whether that purpose be user-driven, configuration-driven, or some sort of AI-driven.’ (cf. Roy Fielding’s comments [here](https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven)). – Géry Ogam May 23 '21 at 22:38
  • @MarkSeemann And you can actually send `PUT` or `DELETE` HTTP requests in browsers using the Javascript object `XMLHttpRequest`. – Géry Ogam May 23 '21 at 22:48

2 Answers2

2

I believe you are correctly interpretting Fielding's thesis in the first case, but not the second.

Your interpretation of "preferences" seems exactly correct: it's perfectly reasonable to have multiple resources whose representations include the same information, but different presentation, like having a dark theme and a light theme as parallel resource structures.

But I believe that you misinterpret Fielding's proposal of "client-side shopping basket". He's not proposing introducing server side resources to be edited (after all, this capability already exists in the web we have today); but rather the introduction of a general purpose language for storing interesting pieces of client state on the client.

In other words, Fielding is talking about introducing within the HTML standard some controls (similar to the controls of a web form) that would allow the human to save some information would would later be loaded into a form when actually placing an order.

Imagine, if you will, a special kind of form that, when submitted, edits a resource that is local to the web browser itself. So you could pick items out of a catalog, and in doing so your local shopping cart resource would be modified. When you were ready to check out, the contents of your shopping cart would be available to sent to the server.

In the same way that forms are general purpose, and can be used for many different domains, so to we would want this shopping cart plumbing to be general purpose, so that it could be used for any sort of "copy this information to be used later" mechanism.

The trick (that didn't happen) is defining a standard and then getting everybody (browsers makers) to implement those standards in similar enough ways that everything just works.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91
  • Thanks for the feedback. About the shopping cart example, I also thought about your alternative interpretation. This can already be implemented with the [History API](https://html.spec.whatwg.org/#the-history-interface) in HTML5: you simply call `window.history.pushState(data, '', uri)` from Javascript to create a new application state storing the shopping cart `data` in the browser’s application history with an optional change of `uri`, then you can retrieve that `data` with `window.history.state` and send it to the checkout URI using a POST request’s body. Is it what you meant? – Géry Ogam May 24 '21 at 13:46
  • The downside of this approach is that it does not work if Javascript is disabled in the browser, so you have to store the shopping cart data in the URI if you want it to work without Javascript, which is basically the same approach as that of the user preference example. – Géry Ogam May 24 '21 at 13:46
  • Oh sorry I see what you mean now: the whole point of Fielding’s suggestion is precisely to allow manipulation of the application state natively through the hypermedia format of response representations (e.g. a new `` element in HTML that translates clicks to updates of the application state) instead of relying on client-side scripting (e.g. the History API for Javascript). – Géry Ogam May 25 '21 at 16:31
  • About the user preference example, just to be sure, my interpretation was that to carry user preferences stored in a URI across multiple actions, each resource should have a representation with hyperlinks storing the same user preferences than the resource URI (e.g. all hyperlinks in the representation of the resource `/foo?x=bar` should have the query component `x=bar`, so that the information `x=bar` can be propagated). Do you agree with this interpretation? – Géry Ogam May 25 '21 at 22:58
1

As I've also stated in the comments above, I haven't read Fielding's dissertation, but I've been thinking some more about this question and decided to type down my thoughts nonetheless.

I don't think one needs to read the dissertation to understand REST design. I'm not saying this to belittle Fielding's work, which is clearly hugely influential. On the other hand, the dissertation is from 2000, and can't be based on much practical experience. I was a junior developer in 2000, and believe me, REST wasn't a thing. If you did web services at all, SOAP was where it was at.

I've learned REST mainly from Subbu Allamaraju's RESTful Web Services Cookbook and Ian Robinson, Jim Webber, and Savas Parastatidis' REST in Practice. It seems to me that these books are based on more practical experience with developing production services than Fielding could possibly have had when he wrote the dissertation.

All that said, I think I can parse the Fielding quote about a shopping basket:

defining the semantics of shopping items within the hypermedia data formats, allowing the user agent to select and store those items within their own client-side shopping basket, complete with a URI to be used for check-out when the client is ready to purchase

Notice that it talks about a client-side shopping basket. This means that it's the client's responsibility to keep track of state.

The way that I interpret this is that each shopping item is a separate resource, which is hardly controversial. In REST, resources are identified by address, so a shopping basket would simply be a collection of URLs:

/products/12345
/products/56789
/products/90125

A client would have to maintain a list of resource addresses like the above list. Once it's ready to check out, it'd POST the list to the URI given to it for that purpose:

POST /check-out HTTP/1.1
Content-Type: text/plain
/products/12345
/products/56789
/products/90125

Here, I've just used a newline-separated plain-text list, but one could also encode the data in XML or JSON (the latter of which also wasn't really a thing in 2000).

I don't think that I'd design a RESTful shopping basket quite like that, but that's how I interpret the above quote.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • 1
    "the dissertation is from 2000, and can't be based on much practical experience." - I suppose it seems that way, however, that's due to the unfortunate fact that the industry has misappropriated the name for a different concept. Fielding's REST and industry REST are really two different things. The dissertation is *not at all* about the design of (RPC-based) web services, it describes, somewhat abstractly, the architectural constraints and properties of what he terms "Internet-scale distributed hypermedia system", really the World Wide Web (with 10+ years of history at the time). – Filip Milovanović May 25 '21 at 09:06
  • @FilipMilovanović That's fair criticism. As I wrote, I haven't read the dissertation. I debated with myself whether I should answer the question at all, but the OP had asked me (out of band) to consider this question, based on other work I had done on REST APIs in the modern interpretation of the word. I may have misunderstood the intention in such a way that I believed that this was also the context here. If that was wrong, I apologise. – Mark Seemann May 25 '21 at 13:35
  • Thanks for sharing your interpretation Mark. Yes I was interested in it as you have read *RESTful Web Services Cookbook*, while I haven’t. Your suggestion seems to be what Roy Fielding suggests (except that he also specifies that the translation of a user click on a product to an addition of its URI to the local shopping cart should be doable natively by an understanding of the hypermedia format instead of relying on client-side scripting like Javascript in the browser). By the way, in a shopping cart, we also need the quantity information, so would you add duplicate URIs or a quantity field? – Géry Ogam May 25 '21 at 16:20
  • 1
    @Maggyero The actual format is up for negotiation. You could add duplicate URLs, or add a quantity column or property, depending on the format. But as I wrote, I probably wouldn't design a shopping basket like this; I think that a *shopping basket* resource might make more sense, but ultimately, it depends on which exact problem you're solving. – Mark Seemann May 25 '21 at 17:53
  • So instead of storing the shopping cart on the client, you would store it on the server? I see it like this: you create a new shopping cart for the user with a `POST` request to `/shopping-cart`, which returns `/shopping-cart/123abc`, then you add products to the shopping cart with `POST` requests to `/shopping-cart/123abc` enclosing the product URI `/products/456def`, and finally you go to check out with a `POST` request to `/check-out` enclosing the shopping cart URI `/shopping-cart/123abc`. Is it what you had in mind? – Géry Ogam May 25 '21 at 23:36
  • 1
    @Maggyero Yes, that's one way to do it. You could also have one shopping cart per user, instead of creating new ones: `/users/1234/cart`, which dispenses with the need to first create the resource. It depends on how you'd like the system to work, which is (also) a business decision, as much as a technical question. – Mark Seemann May 26 '21 at 05:19
  • @Maggyero Why is a server-side resource a good alternative to a client-side shopping basket? Again, it depends on the use cases you want to support, but with a server-side shopping basket, you can add to basket from one client, but check out later from another client. With a client-side basket, the basket is lost if you resume shopping on a new client (e.g. going from your phone to your laptop, or vice versa). Again, there are non-technical concerns to take into account as well. – Mark Seemann May 26 '21 at 05:22
  • But if I interpreted correctly, one should never include user identifiers in URIs (so no `/carts/123` or `users/123/cart`), cf. [§ 6.2.5](https://www.ics.uci.edu/%7Efielding/pubs/dissertation/evaluation.htm#sec_6_2_5) of Roy Fielding’s doctoral dissertation: ‘Although the URI design matches REST's architectural notion of identifiers, syntax alone is insufficient to force naming authorities to define their own URI according to the resource model. One form of abuse is to include information that identifies the current user within all of the URI referenced by a hypermedia response representation. – Géry Ogam May 26 '21 at 20:17
  • … Such embedded user-ids can be used to maintain session state on the server, track user behavior by logging their actions, or carry user preferences across multiple actions (e.g., Hyper-G's gateways [84]). However, by violating REST's constraints, these systems also cause shared caching to become ineffective, reduce server scalability, and result in undesirable effects when a user shares those references with others.’ – Géry Ogam May 26 '21 at 20:17
  • @Maggyero I'm not sure I can be of much more help to you; I find that quote rather opaque. Practical experience tells me that [including user IDs in URIs is the way to go](https://blog.ploeh.dk/2021/04/19/consider-including-identity-in-urls). One reason is exactly because of cacheability, but if the concern is that clients may hack URI templates, then [you can sign the addresses](https://blog.ploeh.dk/2020/10/26/fit-urls). – Mark Seemann May 27 '21 at 05:11
  • I agree that Fielding’s prose is quite opaque here. Thanks for this very interesting article. And it does not seem to conflict with Fielding’s quote since you suggest to put resource sub-identifier in the URI (which is the resource identifier) but to leave the client identifier (what Fielding calls the user identifier) in the `Authorization` header field. – Géry Ogam May 27 '21 at 20:57
  • There is a little typo in your article: ‘The API checks the that the’ – Géry Ogam May 27 '21 at 20:58
  • This discussion on identifiers reminds me of [that question](https://softwareengineering.stackexchange.com/q/411571/184279) that I had last year while trying to design a data model. An identifier denotes a unique entity within a given set of entities, i.e. in a *context* (or *[namespace](https://en.wikipedia.org/wiki/Namespace)*). For instance, a filename denotes a unique file within a given directory (directory + filename -> file). – Géry Ogam May 27 '21 at 23:39
  • So for REST, a resource identifier denotes a unique representation set within a given user’s application (user + URI -> representation set). And as your article explains very well, everything that is not part of the user identity should be part of the resource identity, otherwise the resource is not fully identified in the user’s application context, which violates the identification of resources constraint for a [uniform interface](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5). – Géry Ogam May 27 '21 at 23:39
  • Sorry Mark, I think I misinterpreted Fielding’s quote on the inclusion of user identifiers in URIs, cf. these two comments in [Robert Bräutigam’s answer](https://softwareengineering.stackexchange.com/a/426761/184279): – Géry Ogam Jun 05 '21 at 20:43
  • ‘Fielding talks about including userid in all URIs for the purpose of tracking the user on the server. It's the same thing that Java Servlets did with the "sessionId" parameter that was present when cookies were not available. They are tracking session state on the server, which is clearly not stateless. And they make shared caching impossible as a bonus. None of those is an issue for server-side carts. Those are valid resources, as such part of the "server state", with whatever URIs the server deems appropriate.’ – Géry Ogam Jun 05 '21 at 20:43
  • ‘It's not the userid itself that is the problem, but how you use it. If it is part of a proper server resource, it is not a problem. If it is used as a session state key, it is a problem. It's your shopping cart after all. Sending a link to someone else, caching it or bookmarking it will work as expected. Again, because it is a proper resource, i.e. "server state". It is not as clear cut as "no userid shall ever be part of any URIs". That is not what Fielding is saying in my interpretation.’ – Géry Ogam Jun 05 '21 at 20:48