A client makes a CORS request using IE8 or IE9 to my domain which uses Spring 3.1 - like so.
if ($.browser.msie && window.XDomainRequest)
{
var xdr = new XDomainRequest();
xdr.open("post", "http://example.com/corstest/testPost");
xdr.onload = function() {
var dom = new ActiveXObject("Microsoft.XMLDOM");
dom.async = false;
dom.loadXML(xdr.responseText);
$("#corsdiv").html(xdr.responseText);
};
xdr.send("param1=abc");
return false;
}
else
{
$.ajax({
url: "http://example.com/corstest/testPost",
type: "POST",
data: "param1=abc",
success: function( data ) {
$("#corsdiv").html(data);
},
});
return false;
}
At server, in the controller:
@RequestMapping(value = "/testPost", method = RequestMethod.POST)
public @ResponseBody String testPost(@RequestParam Map<String,String> body, Model model, HttpServletRequest request)
{
logger.info("Content-type: " + request.getContentType() + ";" + request.getContentLength() + ";" + request.getParameter("param1"));
logger.info("body:" + body.toString() );
return "Success";
}
gives the following output:
For IE9:
INFO : Content-type: null;10;null
INFO : body:{}
For Firefox:
INFO : Content-type: application/x-www-form-urlencoded; charset=UTF-8;10;abc
INFO : body:{param1=abc}
I am aware that for a IE8/9 CORS request, only text/plain is supported for the request's Content-Type header. (Reference: http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx) From what I understand that's the reason Spring does not bind request from IE8/IE9 - as it expects application/x-www-form-urlencoded as the Content-Type.
I used a filter to intercept requests coming in and set the ContentType to "application/x-www-form-urlencoded; charset=UTF-8" for all requests (right now for testing purposes).
Reffering to Modify request parameter with servlet filter, I wrapped the HttpServletRequest in HttpServletRequestWrapper, which overrides the getContentType, getCharacterEncoding, getHeader, getHeaderNames and getHeaders methods, and passed it to the chain.doFilter() method on a Filter.
The output I get is:
For IE9:
INFO : Content-type application/x-www-form-urlencoded; charset=UTF-8;10;null
INFO : body:{}
For Firefox:
INFO : Content-type: application/x-www-form-urlencoded; charset=UTF-8;10;abc
INFO : body:{param1=abc}
The binding does not kick in.
My question is:
- Is it possible to get spring to bind data from the IE8/9 CORS request using this approach. If it is - what am I doing wrong?
- If not - why, and what other options do I have to make this work?
UPDATE:
On further investigation I found that Spring binds the request data in WebRequestDatabinder using request.getParameterMap() - which I did not override in the HttpServletRequestWrapper.
The following are the conditions that must be met before post FORM data will be populated to the parameter set by the servlet container(http://java.boot.by/wcd-guide/ch01s02.html):
- The request is an HTTP or HTTPS request.
- The HTTP method is POST.
- The content type is application/x-www-form-urlencoded.
- The servlet has made an initial call of any of the 'getParameter' family of methods on the request object.
Since the servlet container sees the content-Type as text/plain, it does not parse the request body into a Parameter Map. Spring finds an empty Parameter Map and hence does not bind data.