I was pleased to learn that FF 3.5 supports the W3C's proposed
Access Control for Cross-Site Requests which provides
a way for web servers to support cross-site access controls that
enable secure cross-site data transfers. Of particular note is that
FF 3.5 claims support for this capabilitiy with XMLHttpRequest (see
https://developer.mozilla.org/en/HTTP_access_control)
I'm having a problem though getting working in accordance with the
standard the following code which which uses XMLHttpRequest to
generate an HTTP POST.
var xhr = new XMLHttpRequest( );
var someURL = "http://some-domain-here.com/
some_resource_here.html";
var params = "parameter=value goes here.";
xhr.open("POST", someURL, true);
xhr.setRequestHeader("Content-type", "application/x-www-
form-urlencoded");
xhr.setRequestHeader("Content-length", params.length);
xhr.setRequestHeader("Connection", "close");
xhr.onerror = errorHandler;
xhr.onreadystatechange =
function() {
if(xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
xhr.send(params);
function errorHandler( e ) {
alert( "Error processing XMLHttpRequest: " +
e.target.status );
}
My experience contradicts the documentation in that this code leads to
a
"preflighted" request that first sends an HTTP OPTIONS request header
to the resource on the other domain, in order to determine whether the
actual request is safe to send. The documentation states
=============================================================
In particular, a request is preflighted if:
* It uses methods other than GET or POST. Also, if POST is used to
send request data with a Content-Type other than application/x-www-
form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST
request sends an XML payload to the server using application/xml or
text/xml, then the request is preflighted.
* It sets custom headers in the request (e.g. the request uses a
header such as X-PINGOTHER)
==============================================================
My POST uses Content-Type: application/x-www-form-urlencoded
and is not setting any custom headers.
Why the preflighted request?
Any help would be appreciated.
I exhausted my options trying things with my client code to determine
why this is not working in accordance with the W3C's recommended
Access Control for Cross-Site Requests standard (see http://www.w3.org/TR/access-control/
for the proposed standard and https://developer.mozilla.org/en/HTTP_access_control
for Mozilla's explanation of their implementation).
Instead, I took a look at Mozilla's source code implementation of the
XMLHttpRequest in FF 3.5 and found the following in
nsXMLHttpRequest.cpp
=======================================================
nsresult
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel*
aChannel)
{
nsresult rv;
// First check if this is a same-origin request, or if cross-site
requests
// are enabled.
if ((mState & XML_HTTP_REQUEST_XSITEENABLED) ||
CheckMayLoad(mPrincipal, aChannel)) {
return NS_OK;
}
// This is a cross-site request
mState |= XML_HTTP_REQUEST_USE_XSITE_AC;
// Check if we need to do a preflight request.
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI);
nsCAutoString method;
httpChannel->GetRequestMethod(method);
if (!mACUnsafeHeaders.IsEmpty() ||
HasListenersFor(NS_LITERAL_STRING(UPLOADPROGRESS_STR)) ||
(mUpload && mUpload->HasListeners())) {
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
}
else if (method.LowerCaseEqualsLiteral("post")) {
nsCAutoString contentTypeHeader;
httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("Content-Type"),
contentTypeHeader);
nsCAutoString contentType, charset;
rv = NS_ParseContentType(contentTypeHeader, contentType, charset);
NS_ENSURE_SUCCESS(rv, rv);
if (!contentType.LowerCaseEqualsLiteral("text/plain")) {
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
}
}
else if (!method.LowerCaseEqualsLiteral("get") &&
!method.LowerCaseEqualsLiteral("head")) {
mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
}
return NS_OK;
}
========================================================
Looks to me like HTTP POSTs with anything other than a Content-Type of
"text/plain" get preflighted. That overlooks "application/x-www-form-
urlencoded" and "multipart/form-data" which, according to the proposed
standard, should not require "preflighting".
I changed my Content-Type to "plain/text" and the Cross Domain request
made it through without preflighting but the (Java-based) server side
code that processes the request fails because it is expecting, in
general, a posting of HTML FORM data with an associated Content-Type
of "application/x-www-form-urlencoded".
Can someone in the development group confirm this and, if necessary,
log a bug report?
Kevin H.
I am not from the development group, but having the same problem, a
request is NOT preflighted only if it is "text/plain". However, my
requirement is a non-preflighted request with Content-Type of
"application/x-www-form-urlencoded", trying to find a workaround for
this one.
I'm experiencing this exact same thing. A request is NOT preflighted
only if it is "text/plain". However, my requirement is a non-
preflighted request with Content-Type of "application/x-www-form-
urlencoded". Has anyone found a workaround to this yet?