Win a copy of Classic Computer Science Problems in Swift this week in the iOS forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

REST, persistence and sessions  RSS feed

 
Saloon Keeper
Posts: 8763
163
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As we know, RESTful web applications only expose stateless operations to get anything done. All information that is needed by the server to perform the operation is sent with the request. Let's say we have a repository holding instances of some resource type, and the client can send a request to view the details of the resource:
Imagine we want to delete the last resource that the user accessed:
This is not RESTful, because it requires the server to keep track of what the last accessed resource was. Instead, the client needs to explicitly send the ID of the resource they want to delete:

Now, some say that sessions are not RESTful, because they require the server to keep track of the session data. This is untrue. All session data can be stored in the session cookie, which is sent by the client on each request. Another solution is to send only a session ID which identifies a persistent resource containing the session data:
After all, if we are allowed to store any old resource in a database and manipulate it using an identifier sent by the client, then why not treat sessions the same way?

So, assuming sessions can be treated as resources, and the identifier can be sent with the request in a session cookie, we can make requests like this:

For some reason, there are many opponents to handling sessions in RESTful applications this way. They insist that you have to send an access token with every request. It's not immediately clear to me what separates an access token from a session ID. It's also not clear to me why the server must be stateless, but somehow the server IS allowed to persist resources to a database. If I write a repository that internally uses a concurrent map instead of a database connection, why is that not RESTful? If the two aren't different, then is storing resources in a database really RESTful? If it isn't, can RESTful applications get anything useful done?

I welcome all thoughts on this topic.
 
Rancher
Posts: 950
9
Java Linux Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In terms of architecture, I'll be looking for reliability and typically this leads to horizontally scaling out.  So with session identifiers your going to be using sticky sessions, which limit reliability.  A shared database approach, holding session information, offers more reliability.  Most databases offer replication and redundancy with failover features.  Of course this design has an impact on performance. 

Currently learning about [AWS] lambda and server-less, so that's a major influence on my current thinking.  Without a server, you don't really have a session so its a connection to either a shared cache or database (or both).

Not going to comment on what rest methods seems to be stateful or stateless, just prefer them to be idempotent.  Actually I always preferred idempotent methods in any language or design.   
 
Bartender
Posts: 19372
87
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There are sessions and then there are "sessions".

A ReSTful server should avoid using J2EE HttpSessions. That's because (absent clustering), the session ID in the jsessionid cookie or URL decoration is tied to one particular server instance. And even with clustering, the session ID is still limited to that cluster, which make it difficult to scale up to multi-clusters. The hallmark of ReST is that you should be able to set up a whole raft of unrelated servers and, given a suitable dispatcher/load balancer, send a ReST request to any server with identical results.

On the other hand, even if individual operations are ReSTful, they might be part of an overall workflow, which, by definition, is a stateful environment. So it's entirely likely that you'd need a mechanism that preserves identify on the client side between ReST requests. The only difference being that the session ID isn't in the webapp server, it's in the behind-the-scenes infrastructure that the ReST server invokes. Instead of a J2EE jsessionid, you define your own session ID - not backed by an HttpSession object.

Whether you maintain that ID in a cookie or via URL rewriting or as part of a form submit is really immaterial. A cookie is convenient since cookies are thrown back and forth automatically, whereas you have to explicitly invoke a URL rewriter or inject a sessionid value object into a form submit.

As for passing object IDs back and forth (as opposed to tracking them in a server-end session), I don't like that whether the app is ReSTful or not. If you permit the client to send an object ID, there's an opportunity for a bad client to change that ID to something illicit. Unless the request really is intended to be a general-purpose handler as opposed to, say, acting on workflow functions, that's a very high security risk. Sending actual objects back and forth is even worse - high bandwidth and low security.

Incidentally, J2EE jsessionid carries absolutely NO session data. It's merely a "randomly" generated hash key that tracks the HttpSession map in the server. It's hard to counterfeit, since the odds of an attacker stumbling on a live key by accident or brute force are very, very low. And to further protect the session, J2EE servers assign a completely different jsessionid to the HttpSession the instant the user switches to HTTPs, so even a man-in-the-middle cannot determine that ID without being able to decrypt the request first. Which is why you should never attempt to manually cache a jsessionid.
 
Stephan van Hulst
Saloon Keeper
Posts: 8763
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you both. Am I correct in deducing that the short answer to my doubts why resources in general (whether you consider a "session" a resource or not) can be persisted to databases without losing RESTfulness, is that the whole infrastructure that provides the persistence can be considered a single globally accessible service that all servers can use concurrently and reliably? This as opposed to say, an in-memory repository that isn't replicated?
 
Tim Holloway
Bartender
Posts: 19372
87
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's all about appearances. A Restful system should act precisely the same whether there's one webapp server talking to one instance of a database (or other resources) or there's 10,000 webapp servers and hundreds of database instances. So ReST works best when there are no apserver-local sessions and there's a good load-balancing dispatcher to ensure that the incoming requests get routed to the servers that can best take the load. And any resource that's only accessible on a single unique server breaks ReST. Or at least bottlenecks it.

To be ideologically pure, I suppose that a client should be able to send out requests in any order (meaning that the system was truly stateless), but there are too many practical uses for a stateful system that uses ReST for scalability to make that something that anyone but an ideological idiot would dismiss.
 
Stephan van Hulst
Saloon Keeper
Posts: 8763
163
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot Tim, this discussion has certainly given me some great insights.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!