Take the 2-minute tour ×

This is a pretty esoteric issue that I can't produce a small test case for, so sorry in advance. But maybe someone has run into something like it previously.

I have code like this (using restify):

server.put("/whatever", function (serverRequest, serverResponse, next) {

    serverRequest.on("data", function (chunk) {
        console.log("from outside", chunk);

    doSomeAsyncStuff(function (err) {
        serverRequest.on("data", function (chunk) {
            console.log("from inside", chunk);
        serverRequest.on("end", function () {


When I hit this server using CURL, this works great. But when I hit it with XMLHttpRequest, I get one less "from inside" log line than I do "from outside" log lines. It seems one of the data events is getting lost, despite my best efforts to pause ASAP.

Here is the CURL command I am using:

curl -X PUT -T file.pdf http://localhost:7070/whatever -v

And here is the XMLHttpRequest code (works in recent versions of Chrome):

var arrayBuffer = fromElsewhere();
var xhr = new XMLHttpRequest();

xhr.open("PUT", "http://localhost:7070/whatever");
xhr.setRequestHeader("Content-Length", arrayBuffer.byteLength);
xhr.setRequestHeader("Content-Type", "application/pdf");

One notable difference is that CURL seems to send Expect: 100-continue before uploading, whereas XMLHttpRequest does not. I tried adding that header manually but of course it didn't actually do much (i.e. Chrome did not wait for a response, it just sent up all the PDF data along with the original request). Even so, I don't know why this would effect things.

share|improve this question
add comment

1 Answer

up vote 3 down vote accepted

Somewhat predictably, this didn't have anything to do with curl vs. XMLHttpRequest, but instead with the fact that serverRequest.pause is only advisory; it doesn't actually pause right away. That is, it's pretty much useless.

So presumably in the CURL case the timing was nice enough that pause actually worked as expected, whereas in the XMLHttpRequest case the timing was off, and one of the "from outside" data events managed to slip through the "advisory" pause.

There are apparently various fixes for this, discussed in the thread, but I'm still pretty shaky on this whole streams/buffers universe so I won't try to recommend one in this answer.

I've added a documentation pull request in the hopes nobody else tries to use pause assuming that it actually works.

share|improve this answer
Well, pause works but as you mention, it's advisory, and asynchronous. A very useful use-case of pause is within a proxy: you read from upstream, and write to the client. If the write to the client returns false, it means that the buffer is full, and you can send a pause to the backend. You will probably receive a few extra chunks of data from the backend, but not all the file. Without the pause, proxying a 1 GB file causes the whole file to be buffered into memory (and your Node.js process to explode). I hope this helps! –  jpetazzo Nov 4 '12 at 15:46
add comment

Your Answer


