POST Request using req.write() and req.end()

I'm trying to do HTTP POST using the the request module from a node server to another server.

My code looks something like,

var req = request.post({url: "http://foo.com/bar", headers: myHeaders});
...
...
req.write("Hello");
...
...
req.end("World");

I expect the body of the request to be "Hello World" on the receiving end, but what I end up with is just "".

What am I missing here?

Note: The ellipsis in the code indicates that the write and the end might be executed in different process ticks.

It looks to me as if you are getting missed Request http.clientRequest/http.serverRequest

If you want to make a post to a server with request what you want to do is something like

request({ method:"post", url: "server.com", body:"Hello World"}, callback);

As 3on pointed, the correct syntax for a POST request is

request({ method:"post", url: "server.com", body:"Hello World"}, callback);

You also have a convenience method:

request.post({ url: "server.com", body:"Hello World"}, callback);

But from your question it seems like you want to stream:

var request = require('request');
var fs = require('fs');

var stream = fs.createWriteStream('file');

stream.write('Hello');
stream.write('World');

fs.createReadStream('file').pipe(request.post('http://server.com'));

Update:

  • You may break the chunks you write to the stream in any way you like, as long as you have the RAM (4mb is peanuts but keep in mind that v8 (the javascript engine behind node) has an allocation limit of 1.4GB I think);
  • You may see how much you "wrote" to the pipe with stream.bytesWritten where var stream = fs.createWriteStream('file') as you see in the piece of code above. I think you can't however know how much the other end of the pipe got, but bitesWritten should give you a pretty decent approximation.
  • You can listen to the data and end events of both stream and request.post('http://server.com')

I managed to make the code written in the question here valid and work as expected by modifying the request module a bit.

I noticed a block of code in request's main.js in the Request.prototype.init function (at line 356),

process.nextTick(function () {
    if (self._aborted) return

    if (self.body) {
      if (Array.isArray(self.body)) {
        self.body.forEach(function (part) {
          self.write(part)
        })
      } else {
        self.write(self.body)
      }
      self.end()
    } else if (self.requestBodyStream) {
      console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.")
      self.requestBodyStream.pipe(self)
    } else if (!self.src) {
      if (self.method !== 'GET' && typeof self.method !== 'undefined') {
        self.headers['content-length'] = 0;
      }
      self.end();
    }
    self.ntick = true
  })

I'm now overriding this function call by adding a new option (endOnTick) while creating the request. My changes: Comparing mikeal/master with GotEmB/master.