WebKit "Refused to set unsafe header 'content-length'"

user35288 picture user35288 · Apr 12, 2010 · Viewed 77.4k times · Source

I am trying to implement simple xhr abstraction, and am getting this warning when trying to set the headers for a POST. I think it might have something to do with setting the headers in a separate js file, because when i set them in the <script> tag in the .html file, it worked fine. The POST request is working fine, but I get this warning, and am curious why. I get this warning for both content-length and connection headers, but only in WebKit browsers (Chrome 5 beta and Safari 4). In Firefox, I don't get any warnings, the Content-Length header is set to the correct value, but the Connection is set to keep-alive instead of close, which makes me think that it is also ignoring my setRequestHeader calls and generating it's own. I have not tried this code in IE. Here is the markup & code:

test.html:

<!DOCTYPE html>
<html>
    <head>
        <script src="jsfile.js"></script>
        <script>
            var request = new Xhr('POST', 'script.php', true, 'data=somedata',  function(data) { 
                console.log(data.text); 
            });
        </script>
    </head>
    <body>
    </body>
</html>

jsfile.js:

function Xhr(method, url, async, data, callback) {
    var x;
    if(window.XMLHttpRequest) {
        x = new XMLHttpRequest();

        x.open(method, url, async);

        x.onreadystatechange = function() {
            if(x.readyState === 4) {
                if(x.status === 200) {
                    var data = {
                        text: x.responseText,
                        xml: x.responseXML
                    };
                    callback.call(this, data);
                }
            }
        }

        if(method.toLowerCase() === "post") {
            x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            x.setRequestHeader("Content-Length", data.length);
            x.setRequestHeader("Connection", "close");
        }

        x.send(data);
    } else {
        // ... implement IE code here ...
    }
    return x;
}

Answer

bobince picture bobince · Apr 12, 2010

it is also ignoring my setRequestHeader calls and generating its own

Yes, the standard says it must:

For security reasons, these steps should be terminated if header is [...]

  • Connection
  • Content-Length

Messing around with those could expose various request smuggling attacks, so the browser always uses its own values. There's no need or reason to try to set the request length, as the browser can do that accurately from the length of data you pass to send().