urllib

Request HTTP URLs in a complex world ā basic
and digest authentication, redirections, timeout and more.
Install
npm install urllib
Usage
TypeScript and ESM
import { request } from 'urllib';
const { data, res } = await request('http://cnodejs.org/');
console.log('status: %s, body size: %d, headers: %j', res.status, data.length, res.headers);
CommonJS
const { request } = require('urllib');
const { data, res } = await request('http://cnodejs.org/');
console.log('status: %s, body size: %d, headers: %j', res.status, data.length, res.headers);
API Doc
Method: async request(url[, options])
Arguments
- url String | Object - The URL to request, either a String or a Object that return by url.parse.
- options Object - Optional
- method String - Request method, defaults to
GET. Could be GET, POST, DELETE or PUT. Alias 'type'.
- data Object - Data to be sent. Will be stringify automatically.
- content String | Buffer - Manually set the content of payload. If set,
data will be ignored.
- stream stream.Readable - Stream to be pipe to the remote. If set,
data and content will be ignored.
- writeStream stream.Writable - A writable stream to be piped by the response stream. Responding data will be write to this stream and
callback will be called with data set null after finished writing.
- files {Array<ReadStream|Buffer|String> | Object | ReadStream | Buffer | String - The files will send with
multipart/form-data format, base on formstream. If method not set, will use POST method by default.
- contentType String - Type of request data. Could be
json (Notes: not use application/json here). If it's json, will auto set Content-Type: application/json header.
- dataType String - Type of response data. Could be
text or json. If it's text, the callbacked data would be a String. If it's json, the data of callback would be a parsed JSON Object and will auto set Accept: application/json header. Default callbacked data would be a Buffer.
- fixJSONCtlChars Boolean - Fix the control characters (U+0000 through U+001F) before JSON parse response. Default is
false.
- headers Object - Request headers.
- timeout Number | Array - Request timeout in milliseconds for connecting phase and response receiving phase. Default is
5000. You can use timeout: 5000 to tell urllib use same timeout on two phase or set them separately such as timeout: [3000, 5000], which will set connecting timeout to 3s and response 5s.
- keepAliveTimeout
number | null - Default is 4000, 4 seconds - The timeout after which a socket without active requests will time out. Monitors time between activity on a connected socket. This value may be overridden by keep-alive hints from the server. See MDN: HTTP - Headers - Keep-Alive directives for more details.
- auth String -
username:password used in HTTP Basic Authorization.
- digestAuth String -
username:password used in HTTP Digest Authorization.
- followRedirect Boolean - follow HTTP 3xx responses as redirects. defaults to true.
- maxRedirects Number - The maximum number of redirects to follow, defaults to 10.
- formatRedirectUrl Function - Format the redirect url by yourself. Default is
url.resolve(from, to).
- beforeRequest Function - Before request hook, you can change every thing here.
- streaming Boolean - lets you get the
res object when request connected, default false. alias customResponse
- compressed Boolean - Accept
gzip, br response content and auto decode it, default is false.
- timing Boolean - Enable timing or not, default is
true.
- socketPath String | null - request a unix socket service, default is
null.
- highWaterMark Number - default is
67108864, 64 KiB.
Options: options.data
When making a request:
await request('https://example.com', {
method: 'GET',
data: {
'a': 'hello',
'b': 'world',
},
});
For GET request, data will be stringify to query string, e.g. http://example.com/?a=hello&b=world.
For others like POST, PATCH or PUT request,
in defaults, the data will be stringify into application/x-www-form-urlencoded format
if content-type header is not set.
If content-type is application/json, the data will be JSON.stringify to JSON data format.
Options: options.content
options.content is useful when you wish to construct the request body by yourself,
for example making a content-type: application/json request.
Notes that if you want to send a JSON body, you should stringify it yourself:
await request('https://example.com', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
content: JSON.stringify({
a: 'hello',
b: 'world',
}),
});
It would make a HTTP request like:
POST / HTTP/1.1
host: example.com
content-type: application/json
{
"a": "hello",
"b": "world"
}
This example can use options.data with application/json content type:
await request('https://example.com', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
data: {
a: 'hello',
b: 'world',
}
});
Options: options.files
Upload a file with a hello field.
await request('https://example.com/upload', {
method: 'POST',
files: __filename,
data: {
hello: 'hello urllib',
},
});
Upload multi files with a hello field.
await request('https://example.com/upload', {
method: 'POST',
files: [
__filename,
fs.createReadStream(__filename),
Buffer.from('mock file content'),
],
data: {
hello: 'hello urllib with multi files',
},
});
Custom file field name with uploadfile.
await request('https://example.com/upload', {
method: 'POST',
files: {
uploadfile: __filename,
},
});
Response Object
Response is normal object, it contains:
status or statusCode: response status code.
-1 meaning some network error like ENOTFOUND
-2 meaning ConnectionTimeoutError
headers: response http headers, default is {}
size: response size
aborted: response was aborted or not
rt: total request and response time in ms.
timing: timing object if timing enable.
socket: socket info
Run test with debug log
NODE_DEBUG=urllib:* npm test
Request with HTTP2
Create a HttpClient with options.allowH2 = true
import { HttpClient } from 'urllib';
const httpClient = new HttpClient({
allowH2: true,
});
const response = await httpClient.request('https://node.js.org');
console.log(response.status);
console.log(response.headers);
Mocking Request
export from undici
import { strict as assert } from 'assert';
import { MockAgent, setGlobalDispatcher, request } from 'urllib';
const mockAgent = new MockAgent();
setGlobalDispatcher(mockAgent);
const mockPool = mockAgent.get('http://localhost:7001');
mockPool.intercept({
path: '/foo',
method: 'POST',
}).reply(400, {
message: 'mock 400 bad request',
});
const response = await request('http://localhost:7001/foo', {
method: 'POST',
dataType: 'json',
});
assert.equal(response.status, 400);
assert.deepEqual(response.data, { message: 'mock 400 bad request' });
Request through a http proxy
export from undici
import { ProxyAgent, request } from 'urllib';
const proxyAgent = new ProxyAgent('http://my.proxy.com:8080');
const response = await request('https://www.npmjs.com/package/urllib', {
dispatcher: proxyAgent,
});
console.log(response.status, response.headers);
Benchmarks
Fork undici benchmarks script
undici@6.19.2
Node.js v18.20.3
āāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāā
ā (index) ā Tests ā Samples ā Result ā Tolerance ā Difference with slowest ā
āāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā 0 ā 'urllib2 - request' ā 10 ā '321.53 req/sec' ā '± 0.38 %' ā '-' ā
ā 1 ā 'http - no keepalive' ā 10 ā '607.77 req/sec' ā '± 0.80 %' ā '+ 89.02 %' ā
ā 2 ā 'got' ā 101 ā '7929.51 req/sec' ā '± 4.46 %' ā '+ 2366.15 %' ā
ā 3 ā 'node-fetch' ā 40 ā '8651.95 req/sec' ā '± 2.99 %' ā '+ 2590.84 %' ā
ā 4 ā 'request' ā 101 ā '8864.09 req/sec' ā '± 7.81 %' ā '+ 2656.82 %' ā
ā 5 ā 'undici - fetch' ā 101 ā '9607.01 req/sec' ā '± 4.23 %' ā '+ 2887.87 %' ā
ā 6 ā 'axios' ā 55 ā '10378.80 req/sec' ā '± 2.94 %' ā '+ 3127.91 %' ā
ā 7 ā 'superagent' ā 75 ā '11286.74 req/sec' ā '± 2.90 %' ā '+ 3410.29 %' ā
ā 8 ā 'http - keepalive' ā 60 ā '11288.96 req/sec' ā '± 2.95 %' ā '+ 3410.98 %' ā
ā 9 ā 'urllib4 - request' ā 101 ā '11352.65 req/sec' ā '± 10.20 %' ā '+ 3430.79 %' ā
ā 10 ā 'urllib3 - request' ā 40 ā '13831.19 req/sec' ā '± 2.89 %' ā '+ 4201.64 %' ā
ā 11 ā 'undici - pipeline' ā 60 ā '14562.44 req/sec' ā '± 2.91 %' ā '+ 4429.06 %' ā
ā 12 ā 'undici - request' ā 70 ā '19630.64 req/sec' ā '± 2.87 %' ā '+ 6005.32 %' ā
ā 13 ā 'undici - stream' ā 55 ā '20843.50 req/sec' ā '± 2.90 %' ā '+ 6382.54 %' ā
ā 14 ā 'undici - dispatch' ā 55 ā '21233.10 req/sec' ā '± 2.82 %' ā '+ 6503.70 %' ā
āāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāā
Node.js v20.15.0
āāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāā
ā (index) ā Tests ā Samples ā Result ā Tolerance ā Difference with slowest ā
āāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā 0 ā 'urllib2 - request' ā 10 ā '332.91 req/sec' ā '± 1.13 %' ā '-' ā
ā 1 ā 'http - no keepalive' ā 10 ā '615.50 req/sec' ā '± 2.25 %' ā '+ 84.88 %' ā
ā 2 ā 'got' ā 55 ā '7658.39 req/sec' ā '± 2.98 %' ā '+ 2200.42 %' ā
ā 3 ā 'node-fetch' ā 30 ā '7832.96 req/sec' ā '± 2.96 %' ā '+ 2252.86 %' ā
ā 4 ā 'axios' ā 40 ā '8607.27 req/sec' ā '± 2.79 %' ā '+ 2485.44 %' ā
ā 5 ā 'request' ā 35 ā '8703.49 req/sec' ā '± 2.84 %' ā '+ 2514.35 %' ā
ā 6 ā 'undici - fetch' ā 65 ā '9971.24 req/sec' ā '± 2.96 %' ā '+ 2895.15 %' ā
ā 7 ā 'superagent' ā 30 ā '11006.46 req/sec' ā '± 2.90 %' ā '+ 3206.11 %' ā
ā 8 ā 'http - keepalive' ā 55 ā '11610.14 req/sec' ā '± 2.87 %' ā '+ 3387.44 %' ā
ā 9 ā 'urllib3 - request' ā 25 ā '13873.38 req/sec' ā '± 2.96 %' ā '+ 4067.27 %' ā
ā 10 ā 'urllib4 - request' ā 25 ā '14291.36 req/sec' ā '± 2.92 %' ā '+ 4192.82 %' ā
ā 11 ā 'undici - pipeline' ā 45 ā '14617.69 req/sec' ā '± 2.84 %' ā '+ 4290.85 %' ā
ā 12 ā 'undici - dispatch' ā 101 ā '18716.29 req/sec' ā '± 3.97 %' ā '+ 5521.98 %' ā
ā 13 ā 'undici - request' ā 101 ā '19165.16 req/sec' ā '± 3.25 %' ā '+ 5656.81 %' ā
ā 14 ā 'undici - stream' ā 30 ā '21816.28 req/sec' ā '± 2.99 %' ā '+ 6453.15 %' ā
āāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāā
Node.js v22.3.0
āāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāā¬āāāāāāāāāāāāā¬āāāāāāāāāāāāāāāāāāāāāāāāāā
ā (index) ā Tests ā Samples ā Result ā Tolerance ā Difference with slowest ā
āāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāā¼āāāāāāāāāāāāā¼āāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā 0 ā 'urllib2 - request' ā 15 ā '297.46 req/sec' ā '± 2.65 %' ā '-' ā
ā 1 ā 'http - no keepalive' ā 10 ā '598.25 req/sec' ā '± 1.94 %' ā '+ 101.12 %' ā
ā 2 ā 'axios' ā 30 ā '8487.94 req/sec' ā '± 2.91 %' ā '+ 2753.52 %' ā
ā 3 ā 'got' ā 50 ā '10054.46 req/sec' ā '± 2.89 %' ā '+ 3280.16 %' ā
ā 4 ā 'request' ā 45 ā '10306.02 req/sec' ā '± 2.87 %' ā '+ 3364.73 %' ā
ā 5 ā 'node-fetch' ā 55 ā '11160.02 req/sec' ā '± 2.87 %' ā '+ 3651.83 %' ā
ā 6 ā 'superagent' ā 80 ā '11302.28 req/sec' ā '± 2.85 %' ā '+ 3699.66 %' ā
ā 7 ā 'undici - fetch' ā 60 ā '11357.87 req/sec' ā '± 2.89 %' ā '+ 3718.35 %' ā
ā 8 ā 'http - keepalive' ā 60 ā '13782.10 req/sec' ā '± 2.97 %' ā '+ 4533.34 %' ā
ā 9 ā 'urllib4 - request' ā 70 ā '15965.62 req/sec' ā '± 2.88 %' ā '+ 5267.40 %' ā
ā 10 ā 'urllib3 - request' ā 55 ā '16010.37 req/sec' ā '± 2.90 %' ā '+ 5282.45 %' ā
ā 11 ā 'undici - pipeline' ā 35 ā '17969.37 req/sec' ā '± 2.95 %' ā '+ 5941.03 %' ā
ā 12 ā 'undici - dispatch' ā 101 ā '18765.50 req/sec' ā '± 3.01 %' ā '+ 6208.68 %' ā
ā 13 ā 'undici - request' ā 85 ā '20091.12 req/sec' ā '± 2.95 %' ā '+ 6654.33 %' ā
ā 14 ā 'undici - stream' ā 45 ā '21599.12 req/sec' ā '± 2.81 %' ā '+ 7161.30 %' ā
āāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāā“āāāāāāāāāāāāāāāāāāāāāāāāāā
License
MIT
Contributors

Made with contributors-img.