adam bien's blog

JAX-RS Response#seeOther, vs. 301, 302, 307 and 308 HTTP Redirections 📎

The JAX-RS Response#seeOther method is a convenience wrapper of the following snippet status(303).location(location).

Status 303 is used for:

"Used to redirect after a PUT or a POST, so that refreshing the result page doesn't re-trigger the operation."

To test HTTP redirections, a ping JAX-RS resource:


@Path("ping")
public class PingResource {
    
    @POST
    @Path("redirect/{status}")
    public Response save(String payload, @Context HttpHeaders headers, @Context UriInfo info, @PathParam("status") int status) {
        String header = headers.getHeaderString("description");
        System.out.println("ping: payload: " + payload + " " + header + " status " + status);
        URI uri = info.getBaseUriBuilder().path("/newping").build();
        return Response.status(status).location(uri).build();
    }
    
}

...will redirect requests to newping JAX-RS class:

@Path("newping")
public class NewPingResource {
    
    @POST
    public Response save(String payload, @Context HttpHeaders headers) {
        String header = headers.getHeaderString("description");
        System.out.println("newping: payload: " + payload + " header " + header);
        return Response.ok("newping: payload: " + payload + " header " + header).build();
    }
}

The 302, 303 and 301 statuses: curl -L -XPOST -H'description: dev' -d'hello,duke' -i http://localhost:8080/redirects/resources/ping/redirect/302 and 303 generate the following log statements:


ping: payload: hello,duke dev status [...]
newping: payload:  header dev

The NewPingResource#save method does not receive the body / payload and the client always receives the following response:

HTTP/1.1 303 See Other
Server: Payara Server  5.194 #badassfish
X-Powered-By: Servlet/4.0 JSP/2.3 (Payara Server  5.194 #badassfish Java/Oracle Corporation/1.8)
Location: http://localhost:8080/redirects/resources/newping
Content-Length: 0
X-Frame-Options: SAMEORIGIN

HTTP/1.1 200 OK
Server: Payara Server  5.194 #badassfish
X-Powered-By: Servlet/4.0 JSP/2.3 (Payara Server  5.194 #badassfish Java/Oracle Corporation/1.8)
Content-Type: text/plain
Content-Length: 29
X-Frame-Options: SAMEORIGIN

newping: payload:  header dev

A 307 and 308 statuses: curl -L -XPOST -H'description: dev' -d'hello,duke' -i http://localhost:8080/redirects/resources/ping/redirect/307 and 308 are passing the entire body to the second resource. The following log statements are created:


ping: payload: hello,duke dev status [...]
newping: payload: hello,duke header dev

The client receives the response including the body sent by the user agent:


HTTP/1.1 307 Temporary Redirect
Server: Payara Server  5.194 #badassfish
X-Powered-By: Servlet/4.0 JSP/2.3 (Payara Server  5.194 #badassfish Java/Oracle Corporation/1.8)
Location: http://localhost:8080/redirects/resources/newping
Content-Length: 0
X-Frame-Options: SAMEORIGIN

HTTP/1.1 200 OK
Server: Payara Server  5.194 #badassfish
X-Powered-By: Servlet/4.0 JSP/2.3 (Payara Server  5.194 #badassfish Java/Oracle Corporation/1.8)
Content-Type: text/plain
Content-Length: 39
X-Frame-Options: SAMEORIGIN

newping: payload: hello,duke header dev    

conclusion

The user agent does not resend the body in the case of 301, 302, 303 HTTP redirections.

307 and 308 were introduced to provide a uniform user agent's (browser, curl, wget, JAX-RS client) behavior and "remove the ambiguity of the behavior when using non-GET methods".

The 5.6kB ThinWAR project was created with Jakarta EE Essentials Archetype and deployed with: wad.sh in 2s