Question

How do I force XmlHttpRequest to add Expect: 100-continue header? How can I make use of this feature in desktop browsers world?

var xmlhttp = new XMLHttpRequest();
var dataToSend = new FormData();
dataToSend.append('some', 'data');
dataToSend.append('token', 'secret-token');

xmlhttp.open("POST", "/post", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Expect", "100-continue");
xmlhttp.setRequestHeader("Custom-Header", "This is custom data");
xmlhttp.send(dataToSend);

Here is the TCP Dump output piece

POST /post HTTP/1.1
Host: 127.0.0.1:3000
Connection: keep-alive
Content-Length: 243
Origin: http://127.0.0.1:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Custom-Header: This is custom data
Content-type: application/x-www-form-urlencoded
Accept: */*
Referer: http://127.0.0.1:3000/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: connect.sid=s%3AAKgYIit0sVHMcI7na85UR_Na.o7uSDBEidLEyQ3cTaGyXlMrPiF3vADrwpnCrkCrJBD0

------WebKitFormBoundary9agFn5mlxh7SUBf7
Content-Disposition: form-data; name="some"

data
------WebKitFormBoundary9agFn5mlxh7SUBf7
Content-Disposition: form-data; name="token"

secret-token
------WebKitFormBoundary9agFn5mlxh7SUBf7--
Was it helpful?

Solution

You cannot force the XMLHttpRequest.setRequestHeader() method to add the Expect header for security reasons, as you can read in the W3C XMLHttpRequest specification:

The setRequestHeader(header, value) method must run these steps:

  1. If the state is not OPENED, throw an "InvalidStateError" exception and terminate these steps.
  2. If the send() flag is set, throw an "InvalidStateError" exception and terminate these steps.
  3. If header does not match the field-name production, throw a "SyntaxError" exception and terminate these steps.
  4. If value does not match the field-value production, throw a "SyntaxError" exception and terminate these steps (note: The empty string is legal and represents the empty header value).
  5. Terminate these steps if header is a case-insensitive match for one of the following headers:

    • Accept-Charset
    • Accept-Encoding
    • Access-Control-Request-Headers
    • Access-Control-Request-Method
    • Connection Content-Length
    • Cookie
    • Cookie2
    • Blockquote
    • Date
    • DNT
    • Expect
    • Host
    • Keep-Alive Origin
    • Referer
    • TE
    • Trailer
    • Transfer-Encoding
    • Upgrade
    • User-Agent
    • Via

...or if the start of header is a case-insensitive match for Proxy- or Sec- (including when header is just Proxy- or Sec-).

The above headers are controlled by the user agent to let it control those aspects of transport. This guarantees data integrity to some extent. Header names starting with Sec- are not allowed to be set to allow new headers to be minted that are guaranteed not to come from XMLHttpRequest.

As a further reference:

Some browsers (Chrome, for example) will also display an error in their "JavaScript Console":

Unsafe header

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top