Sean,

The SlingPostServlet actually sets the Location header of the response based on 
the content that was created/modified by the request so that the browser is 
obliged to issue a new GET request for the subsequent resource if it is a 
synchronous form post, while ajax client code is free to ignore it without 
making a call to render the resource. 

Ideally (from a REST perspective, that is), your POST request would not be 
internally dispatched as a GET request, but would instead make use of the 
Location header in the response to link to the html-rendered confirmation 
resource. GET renditions are typically designed with reverse proxy caching in 
mind, whereas POST responses are generally not cached. This can result in 
unforseen performance impacts when GET responses are returned for POST 
requests.   

As you point out, using redirects can be cumbersome if you are passing a lot of 
contextual data encoded in the Location url, and doing so may be incompatible 
with your security restrictions.  

Instead, the proper route may actually be to persist the post context as a 
"form/confirmation" resource that serves as the Location header target that 
actually exists in the repository for some period of time. By giving the 
context a concrete resource path, you expose its html rendition as a cacheable 
document that can even be bookmarked by the end user for future reference for 
confirmation numbers, submission dates, context-sensitive links, etc. It also 
puts the application in control of the experience of confirming a form 
re-submission, instead of leaving it up to the browser when a POST request 
returns html without redirecting.

Obviously, blindly allowing anonymous requests to create nodes in the 
repository is itself a significant invitation for a DOS attack, so I don't mean 
to suggest that this route is easy or without additional architectural 
considerations, but I think it makes the site experience more predictable from 
the client perspective.

Mark Adamcin
Acquity Group

Sent from a mobile device.

On Feb 26, 2013, at 6:48 PM, Sean Steimer <[email protected]> wrote:

> Is there a recommended approach to handle a POST request in sling where the
> eventual html response rendered to the user depends heavily on the original
> context of the request?
> 
> I've run across this problem in a few different scenarios, but the general
> flow looks something like this:
> - user is presented with an html form
> - form is submitted via HTTP post, which is handled by a servlet
> - servlet process the data, which involves perhaps complex logic such as
> calling some external service
> - user then should see a thank you page confirming successful submission,
> and the thanks you page needs to also include info about what was submitted
> (ie. order details in an eCommerce scenario)
> 
> That last step becomes a problem because of the way post requests are
> handled by the sling post Servlet.  If I simply do
> slingRequest.getRequestDispatcher().forward() the request method remains
> post, and the thank you page doesn't render as expected.  I've gotten
> around this before by using sendRedirect() and setting cookies, or passing
> along url parameters, but when there is a large amount of data involved,
> this becomes less than ideal, plus you are adding an extra server
> round-trip.
> 
> I've also thought about using a custom ServletRequestWrapper that overrides
> getMethod() to always return "GET", but that seems Hacky at best.
> 
> Are there common approaches/patterns/helper classes to make this work that
> I'm just not aware of?
> 
> FWIW, my work in this areas has been with CQ, but my understanding is that
> the limitations I'm running into are based on sling POST servlet handling,
> hence why I'm asking the questions here.

Reply via email to