Can a shopping cart be implemented using REST architecture constraints?
I would like to focus my question with respect to session state. In a typical MVC applicatio
There is nothing wrong with storing the shopping cart as a resource on the server. It is session state that should be stored on the client. https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_3
In order to be stateless, your shopping-cart URI should be able to identify a unique cart without needing to rely on any session information.
For example, /shopping-cart
is probably not sufficient unless there will only ever be one shopping cart throughout your application.
Likely, there will be at least one cart per user. So, you could use something like /user/1234/shopping-cart
or /shopping-cart?userID=1234
.
Even more likely, you will probably need to have multiple shopping-carts per user. So, you will want to give your carts a unique ID like /user/1234/shopping-cart/5678
or just /shopping-cart/5678
.
The point is, everything needed to process the request should be in the request.
A lot of confusion about REST exists because lots of people hear about REST constraints and think they are rules that are applied for no reason other than following the architecture as an end in itself.
The real question you should be asking is why the stateless constraint exists in REST, and what advantages do you get from following it. Keep in mind that REST is an architectural style intended for long-term evolution of large-scale distributed systems. You simply won't have the problems REST is supposed to solve in a small-scale application where a single database holds all your information.
The stateless constraint induces the property of visibility, reliability and scalability. Visibility is improved because a monitoring system does not have to look beyond a single request datum in order to determine the full nature of the request. Reliability is improved because it eases the task of recovering from partial failures. Scalability is improved because not having to store state between requests allows the server component to quickly free resources, and further simplifies implementation because the server doesn't have to manage resource usage across requests.
So, being stateless means the client request should have all the information required to process it.
How important is visibility for you? Do you want to be able to see the whole contents of the shopping cart from the client request when you are debugging something, or are you ok with having to get that information from the databases?
How important is reliability? Do you have a large distributed system with several servers and databases, where that matters? If you have a large distributed system where the shopping cart information might be stored in different databases depending on the exact HTTP server that responded the request, if a server fails only another server from that group will be able to fulfill the request and finish the session, or a server from another group will force the client to restart the session. If all the information is contained in the request, then any server can do it.
How important is scalability? If you have a distributed system and you're storing shopping cart information on a single database, it becomes a funnel for all your requests and you lose scalability. If you store it on several databases, you lose reliability as explained above.
So, do you have ambitious long-term goals or is your application going to be large enough that you'll face the problems REST attempts to solve? If you'll always have a few servers and a single database, and you'll use it for every single request, then it doesn't matter if you go stateless or not. You can just have a /shopping_cart
resource or something like that, add stuff to it with POST
requests, and close or delete it when you're done.
If you'll have your data sharded across multiple databases, lots of HTTP servers responding requests, cache servers, etc, and you want to have the ability to provision capacity dynamically by setting up new servers as they're needed and removing them when load is reduced, then go full stateless and leave the shopping cart with the client.
In REST applications, the session state is entirely managed by the client and the request must contain all the necessary information to be understood by the server. If the server requires authentication, for example, each request must contain the credentials.
The REST stateless constraint is defined as the following:
5.1.3 Stateless
[...] each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]
However, the stateless constraint doesn't mean the server shouldn't store any data.
In applications which the session state is managed by the server, it's a common approach storing the shopping cart data in the HTTP session. But a shopping cart is not a session state. And, probably, it should not be entirely managed by the client.
In REST, a shopping cart, can be a resource identified by a URL such as /shopping-cart
and operations can be performed over it. All the shopping cart data can be persisted to a database on the server.
Any information that can be named can be a REST resource, even a shopping cart:
5.2.1.1 Resources and Resource Identifiers
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time. [...]
You can perform operations like these on your shopping cart:
GET /shopping-cart
: Get the shopping cart.
POST /shopping-cart
: Add an item to the shopping cart (sending some data with the item you are adding and the amount in the request body).
DELETE /shopping-cart/1
: Remove an item with id 1
from the shopping cart.
PATCH /shopping-cart
: Update the shopping cart (sending some data to be updated in the request body).
PUT /shopping-cart
: Replace the whole content of the shopping cart (sending some data with the content of your shopping cart in the request body).
DELETE /shopping-cart
: Remove the shopping cart
POST /shopping-cart/order
: Order the shopping cart content
So, observe the client won't store any information about the shopping cart at any time. All the information related to the shopping cart will be stored in the server.
For more information about REST, I do recommend reading the chapter 5 of Roy T. Fielding's dissertation.
Yes you can,
Shopping cart data (added products) can be saved on the clients session, that ain't a problem.
Then once the user hits /checkout, the shopping cart should be persisted on the DB on the server. The key about rest is that every petition the client makes has to contain all data to identify himself, I suggest reading something about JWT or OAuth.
The app itself would work as any other shopping cart app you have seen, most of them do not persist the shopping cart in DB, just store it the clients session.
I think somebody chose very unfortunate name for STATELESS concept and that's why the whole misunderstanding is caused. It's not about storing any kind of resources, but rather about the relationship between the client and the server.
Client: I'm keeping all the resources on my side and send you the "list" of all the important items which need to processed. Do your job.
Server: All right.. let me take the responsibility of filtering what's important to give you the proper response.
Meaning, the server is the "slave" of the client and has to forget about his "master" after each request.