Hi,

Sling currently does not allow to read request parameters in their original 
order. I need this for a migrated servlet code that used to run on other 
servlet containers and was able to preserve the order (see below), thus has URL 
schemes where paramter order is crucial.

Actually it is the java servlet spec that messed up things here: the HTML forms 
definition [1] clearly says that the order in the form encoding should be 
preserved (both for GET and POST), but the servlet API uses the "Map" interface 
and doesn't specify that this has to be an ordered map. Hence most/all the 
servlet containers implement this using a HashMap (Jetty [2], Adobe's CQSE; 
only Tomcat seems to be an exception [3]), and you can't rely on it.

Note that while Sling does try to _ensure_ the order of parameters as noted on 
[4], this only means it keeps the container order, and only for the special 
case of "multipart/form-data" POSTs, where Sling actually does the decoding 
itself and does not use the servlet containers implicit decoding. However, the 
majority of POSTs and the ones I care about are not in multipart.

Now, there can be a workaround: simply parse it yourself:
- GET: use request.getQueryString()
- POST: use request.getReader()

This is what the servlet code base I mention is doing.

However, the POST case relies on the fact that getReader() hasn't been called 
yet. But this is easily the case with form POSTs, since the first 
request.getParameter() will trigger decoding of the request body. And in Sling 
there will usually be at least one authentication handler that needs to do a 
request.getParameter(), and authentication handlers come before any servlet 
filter, so no luck to work around that.

The proper way IMO would be to have sling take care of the 
correctly-ordered-re-decoding. This would need to be a change mostly in 
ParameterSupport [5] of the sling engine. It should probably be disabled by 
default (otherwise all parameters would always get decoded twice, once in the 
container and once in Sling) and could be opt-in on a per servlet basis - via 
means of some "sling.servlet.orderedparameters" option. Since the servlet is 
not resolved at the time of the auth handlers, this might in fact be tricky to 
do.

WDYT?

[1] http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
[2] 
http://download.eclipse.org/jetty/stable-9/xref/org/eclipse/jetty/util/MultiMap.html#33
[3] 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/http/Parameters.java?revision=1525696&view=markup
[4] 
http://sling.apache.org/documentation/the-sling-engine/request-parameters.html
[5] 
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/parameters/ParameterSupport.java?view=markup

Cheers,
Alex

Reply via email to