Refining redirect semantics in the Servlet API

This post is bike shedding, but as bike shedding go, it’s very important to write about it.

In web applications, it’s necessary to prevent impatient users from POSTing the same data over and over again. For example, to avoid the pain of putting the same item into the basket multiple times because of a browser refresh.

To implement that, there’s a good practice, called the POST/redirect/GET pattern:

POST/redirect/GET pattern,

This week, I read again the list of HTTP status codes. In particular, the following specific snippet drew my attention:

302 Found

This is an example of industry practice contradicting the standard. The HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect (the original describing phrase was "Moved Temporarily"), but popular browsers implemented 302 with the functionality of a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307 to distinguish between the two behaviours. However, some Web applications and frameworks use the 302 status code as if it were the 303.

303 See Other (since HTTP/1.1)

The response to the request can be found under another URI using the GET method. When received in response to a POST (or PUT/DELETE), the client should presume that the server has received the data and should issue a new GET request to the given URI.

Unfortunately, the HttpServletResponse.sendRedirect() method returns the status code 302 instead of 303. Hence, it shouldn’t be used when implementing the above pattern. But how to do it then?

Simply, just go down one abstraction level and manage headers manually:

class FooServlet : HttpServlet() {

    override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) {
        // Do stuff here
        resp.addHeader("Location", "/bar")

This achieves the desired result.

Location HTTP headers
Nicolas Fränkel

Nicolas Fränkel

Nicolas Fränkel is a Software Architect with 15 years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with narrower interests like Software Quality, Build Processes and Rich Internet Applications. Currently working for an eCommerce solution vendor leader. Also double as a teacher in universities and higher education schools, a trainer and triples as a book author.

Read More