joepie91 / node-bhttp

A sane HTTP client library for Node.js with Streams2 support.
62 stars 12 forks source link

pipe to named form field #30

Closed sam0x17 closed 7 years ago

sam0x17 commented 7 years ago

I need to to direct a pipe chain to a named upload field in a bhttp post request. Is there a way I can do this or is it not possible with the API?

joepie91 commented 7 years ago

It's not possible to pipe directly into a form field; that is, it's not possible to do something like this:

one.pipe(two).pipe(bhttp.post(...).formField)

This is an intentional design choice; such an API would become very messy very quickly.

However, due to how Node.js streams work, you can do something like the following:

bhttp.post("https://example.com/foo", {
    fieldOne: "bar",
    fieldTwo: one.pipe(two)
});

In Node.js, when you call pipe and pass in a destination stream, that destination stream is also the return value of the pipe call. This means that if you can specify a single stream somewhere, you can also always specify a chain of piped streams, and it will work the same way.

Of course, all the usual restrictions apply - most notably, streaming data (and sending large binary data in general) will only work with multipart/form-data requests, so the receiving server has to support this.

sam0x17 commented 7 years ago

thanks -- I might be able to reorganize things so the http post starts early and then do all my chaining in there

joepie91 commented 7 years ago

Since streams are asynchronous, you can also just do something like the following, if order of execution is a concern:

let chainedStreams = one.pipe(two);

// do other stuff here

bhttp.post("https://example.com/foo", {
    fieldOne: "bar",
    fieldTwo: chainedStreams
});

Streams are just objects with a standardized API, so you can pass them around and handle them in the same way you can do with any other JS object.

One feature specific to streams, however, is that they won't start "running" until there's a destination to pipe to - so even in the example above, nothing is actually piped into two until the HTTP request starts being sent. The code at the start is just expressing the intention to do so.

sam0x17 commented 7 years ago

Oh ok that's very cool I didn't know that thanks!

sam0x17 commented 7 years ago

update: turns out a really good way of doing this is passing a PassThrough stream, using bhttp.wrapStream on it, and piping to the PassThrough stream once your chain is ready to go.