![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
A sane HTTP client library for Node.js with Streams2 support.
There are already a few commonly used HTTP client libraries for Node.js, but all of them have issues:
http
module is rather low-level, and even relatively simple requests take a lot of work to make correctly. It also automatically uses a limited amount of agents for HTTP requests (in Node.js 0.10), which slows down concurrent HTTP requests when you're streaming the responses somewhere.request
is buggy, only supports old-style streams, has the same 'agent' problem as http
, the documentation is poor, and the API is not very intuitive.needle
is a lot simpler, but suffers from the same 'agent' problem, and the API can be a bit annoying in some ways. It also doesn't have a proper session API.hyperquest
(mostly) solves the 'agent' problem correctly, but has a very spartan API. Making non-GET requests is more complex than it should be.All these issues (and more) are solved in bhttp
. It offers the following:
multipart/form-data
(eg. file uploads), with support for Streams2, and support for legacy streams.bhttp
does not yet use a HTTPS-capable agent. This means that all SSL-related options are currently ignored by default (per Node.js http
documentation).
This does not mean that you cannot use bhttp
for HTTPS requests! If you need secure HTTPS requests, just make sure to specify a custom https
agent.
WTFPL or CC0, whichever you prefer. A donation and/or attribution are appreciated, but not required.
My income consists entirely of donations for my projects. If this module is useful to you, consider making a donation!
You can donate using Bitcoin, PayPal, Gratipay, Flattr, cash-in-mail, SEPA transfers, and pretty much anything else.
Pull requests welcome. Please make sure your modifications are in line with the overall code style, and ensure that you're editing the src/
files, not the lib/
files.
Build tool of choice is babel
; simply run npm run build
while developing, and it will watch for changes.
Be aware that by making a pull request, you agree to release your modifications under the licenses stated above.
A simple example:
var Promise = require("bluebird");
var bhttp = require("bhttp");
Promise.try(function() {
return bhttp.get("http://icanhazip.com/");
}).then(function(response) {
console.log("Your IP is:", response.body.toString());
});
... or, using nodebacks:
var bhttp = require("bhttp");
bhttp.get("http://icanhazip.com/", {}, function(err, response) {
console.log("Your IP is:", response.body.toString());
});
Demonstrating both streaming responses and using a stream in form data for a request:
var Promise = require("bluebird");
var bhttp = require("bhttp");
Promise.try(function() {
return bhttp.get("http://somesite.com/bigfile.mp4", {stream: true});
}).then(function(response) {
return bhttp.post("http://somehostingservice.com/upload", {
fileOne: response,
fileTwo: fs.createReadStream("./otherbigfile.mkv")
});
}).then(function(response) {
console.log("Response from hosting service:", response.body.toString());
});
... or, using nodebacks:
var bhttp = require("bhttp");
bhttp.get("http://somesite.com/bigfile.mp4", {stream: true}, function(err, responseOne) {
var payload = {
fileOne: responseOne,
fileTwo: fs.createReadStream("./otherbigfile.mkv")
};
bhttp.post("http://somehostingservice.com/upload", payload, {}, function(err, responseTwo) {
console.log("Response from hosting service:", responseTwo.body.toString());
})
})
Upload progress events:
var Promise = require("bluebird");
var bhttp = require("bhttp");
Promise.try(function() {
return bhttp.post("http://somehostingservice.com/upload", {
file: fs.createReadStream("./bigfile.mkv")
}, {
onUploadProgress: function(completedBytes, totalBytes) {
console.log("Upload progress:", (completedBytes / totalBytes * 100), "%");
}
});
}).then(function(response) {
console.log("Response from hosting service:", response.body.toString());
});
Download progress events:
var Promise = require("bluebird");
var bhttp = require("bhttp");
Promise.try(function() {
return bhttp.get("http://somehostingservice.com/bigfile.mkv", {stream: true});
}).then(function(response) {
response.on("progress", function(completedBytes, totalBytes) {
console.log("Download progress:", (completedBytes / totalBytes * 100), "%");
});
response.pipe(fs.createWriteStream("./bigfile.mkv"));
});
var Promise = require("bluebird");
var bhttp = require("bhttp");
var session = bhttp.session({ headers: {"user-agent": "MyCustomUserAgent/2.0"} });
// Our new session now automatically has a cookie jar, and also uses our preset option(s).
Promise.try(function(){
return session.get("http://hypotheticalsite.com/cookietest"); // Assume that this site now sets a cookie
}).then(function(response){
return session.get("http://hypotheticalsite.com/other-endpoint"); // This now sends along the cookie!
});
The various error types are documented at the bottom of this README.
Convenience methods that pre-set the request method, and automatically send along the payload using the correct options for bhttp.request
.
bhttp.request
method below.The data
payload can be one of the following things:
Further documentation for these methods, such as the response attributes, can be found in the below section for bhttp.request
.
Makes a request, and returns the response object asynchronously. The response object is a standard http.IncomingMessages
with a few additional properties (documented below the argument list).
Note that (progress) event handlers must be specified in the options
or (in the case of download progress events) as an event listener on the response object - as bhttp
uses Promises, it is not technically possible to return an EventEmitter.
url: The URL to request, with protocol. When using HTTPS, please be sure to read the 'Caveats' section.
options: Optional. Extra options for the request. Any other options not listed here will be passed on directly to the http
or https
module.
false
. Whether the response is meant to be streamed. If true
, the response body won't be parsed, an unread response stream is returned, and the request is kept out of the 'agent' pool.true
. Whether to automatically follow redirects or not (the redirect history is available as the redirectHistory
property on the response).10
. The maximum amount of redirects to follow before erroring out, to prevent redirect loops.false
. Ensures that mulipart/form-data
encoding is used, no matter what the payload contents are.false
. When set to true
, the request payload will be encoded as JSON. This cannot be used if you are using any streams in your payload.false
. When set to true
, the response will always be decoded as JSON, no matter what the Content-Type
says. You'll probably want to keep this set to false
- most APIs send the correct Content-Type
headers, and in those cases bhttp
will automatically decode the response as JSON.false
. Never decode the response, even if the Content-Type
says that it's JSON.multipart/form-data
encoding.bhttp.session()
instead.false
. Many servers don't support multipart/form-data
when it is transmitted with chunked transfer encoding (eg. when the stream length is unknown), and silently fail with an empty request payload - this is why bhttp
disallows it by default. If you are absolutely certain that the endpoint supports this functionality, you can override the behaviour by setting this to true
.false
. Whether to throw away the response without reading it. Only really useful for fire-and-forget calls. This is almost never what you want.false
. Whether to keep the response streams of redirects. You probably don't need this. When enabling this, you must explicitly read out every single redirect response, or you will experience memory leaks!false
. When set to true
, bhttp just prepares the request, and doesn't actually carry it out; useful if you want to make some manual modifications. Instead of a response, the method will asynchronously return an array with the signature [request, response, requestState]
that you will need to pass into the bhttp.makeRequest()
method.(completedBytes, totalBytes, request)
. If the total size is not known, totalBytes
will be undefined
. The request
variable will hold the request object that the progress event applies to - this is relevant when dealing with automatic redirect following, where multiple requests may occur.(completedBytes, totalBytes, response)
. If the total size is not known, totalBytes
will be undefined
. The response
variable will hold the response object that the progress event applies to - this is relevant when dealing with automatic redirect following, where multiple responses may occur. Note that using the progress
event on a response object is usually a more practical option!callback: Optional. When using the nodeback API, the callback to use. If not specified, a Promise will be returned.
A few extra properties are set on the response object (which is a http.IncomingMessage
):
stream
is set to false
(the default), this will contain the response body. This can be either a Buffer or, in the case of a JSON response, a decoded JSON object.keepRedirectResponses
option.bhttp
. You probably don't need this.bhttp
. You probably don't need this.Additionally, there's an extra event on the response
object:
onDownloadProgress
option, except the event will be specific to this response, and it allows for somewhat nicer syntax. Make sure to attach this handler before you start reading the response stream!bhttp
can automatically parse the metadata for the following types of streams:
fs
streamshttp
and bhttp
responsesrequest
requestscombined-stream
streams (assuming all the underlying streams are of one of the types listed here)If you are using a different type of stream, you can wrap the stream using bhttp.wrapStream
to manually specify the needed metadata.
This will create a new session. The defaultOptions
will be deep-merged with the options specified for each request (where the request-specific options have priority).
A new cookie jar is automatically created, unless you either specify a custom cookieJar
option or set the cookieJar
option to false
(in which case no cookie jar is used).
This will return a 'stream wrapper' containing explicit metadata for a stream. You'll need to use it when passing an unsupported type of stream to a data
parameter or formFields
/files
option.
The resulting wrapper can be passed on to the bhttp
methods as if it were a regular stream.
When using the justPrepare
option, you can use this method to proceed with the request after manual modifications. The function signature is identical to the signature of the array returned when using justPrepare
. response
will usually be null
, but must be passed on as is, to account for future API changes.
All these correctly extend the Error
class - this means that you can use them as a .catch
predicate when using Promises, and that you can use instanceof
on them when using the nodeback API.
The base class for all errors generated by bhttp
. You usually don't need this.
You have specified two or more request options that cannot be used together.
The error message will contain more details.
You tried to load a URL that isn't using either the HTTP or HTTPS protocol. Only HTTP and HTTPS are currently supported.
A redirect was encountered that could not be followed.
This could be because the redirect limit was reached, or because the HTTP specification doesn't allow automatic following of the redirect that was encountered.
The error message will contain more details.
Something went wrong while generating the multipart/form-data stream.
Currently, this will only be thrown if you try to use chunked transfer encoding for a multipart stream - a common situation where this can occur, is when you pass in streams with an unknown length.
To resolve this error, you must either explicitly specify the length of the streams using bhttp.wrapStream
or, if the target server supports it, enable the allowChunkedMultipart
option.
The connection timed out.
The connection timeout is defined by the operating system, and cannot currently be overridden.
The response timed out.
The response timeout can be specified using the responseTimeout
option, and it is measured from the start of the request to the start of the response. If no response is received within the responseTimeout
, a ResponseTimeoutError
will be thrown asynchronously, and the request will be aborted.
You should not set a responseTimeout
for requests that involve large file uploads! Because a response can only be received after the request has completed, any file/stream upload that takes longer than the responseTimeout
, will result in a ResponseTimeoutError
.
FAQs
A sane HTTP client library for Node.js with Streams2 support.
The npm package bhttp receives a total of 3,779 weekly downloads. As such, bhttp popularity was classified as popular.
We found that bhttp demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.