HttpClient : Http client
The http
module provides HttpClient
. HttpClient
can easily initiate http requests.
This document focuses on the use of HttpClient. HttpClient supports http and https. http protocol versions are HTTP/1.1.
User can use the following code to import the http
module and access HttpClient
.
var http = require('http');
Support
The following shows HttpClient
module APIs available for each permissions.
In this doc, the client
, request
or req
all indicate HttpClient
object. For convenience, we usually use the request
or req
to refer to the client
object in the example.
User Mode | Privilege Mode | |
---|---|---|
http.HttpClient | ● | ● |
http.request | ● | ● |
http.get | ● | ● |
http.fetch | ● | ● |
client.open | ● | ● |
client.close | ● | ● |
client.request | ● | ● |
client.write | ● | ● |
client.end | ● | ● |
client.destroy | ● | ● |
HttpClient Class
HttpClient
class inherit from HttpClientRequest.
new http.HttpClient(callback, saddr[, tlsOpt])
callback
{Function} Reuqest handler.res
{HttpClientResponse} Response object.
saddr
{Object} Server socket address.tlsOpt
{Object} TLS securely connections options. default: undefined, means use TCP connection.- Returns: {HttpClient} The http client request object.
This method directly creates the HttpClient
object. The user needs to call client.open()
to establish the http connection, call client.request()
to initiate the http request, and call client.close()
to close the http connection after processing the request.
In general, users are recommended to use http.request()
, http.get()
instead of creating an HttpClient
object directly.
http.request(url[, callback][, options[, tlsOpt]])
url
{String} Http url.callback
{Function} Reuqest handler.res
{HttpClientResponse} Response object.
options
{Object} Has the following properties:domain
{socket.AF_INET | socket.AF_INET6} If the url host is provided as a domain name, the domain name is resolved to an ipv4 or ipv6 address based on the domain. default: socket.AF_INET.saddr
{Object} Server socket address. default: Use url parameter resolution, if you request the same domain name multiple times, it is recommended to set this parameter after manual domain name resolution to speed up the request.method
{String} Http method, default: GET.path
{String} The request uri path, default: url parsed path.timeout
{Integer} The request timeout (ms). If the request times out,HttpClient
will close. default: 10000.headers
{Object} Http headers. header key must be lowercase.host
{String} The domain name or IP address of the server to which the request is sent. default: url host.post
{String | Buffer | Object} The request post data, default: undefined.async
{Boolean} true - returnPromise
object; false - returnHttpClient
object,default: false
tlsOpt
{Object} TLS securely connections options. default: undefined, means use TCP connection.- Returns: {HttpClient | Promise} The http client request object or promise object.depend on
async
option.
This HttpClient
object (request object) is created internally and returned from http.request()
.
The response object will be passed to the callback
function.
The http body data can be set in the options.post
. If the options.method
is set to GET, the post data will not be sent. If the options.method
is set to non-GET and the options.post
defines valid data, then request()
automatically end the request. Otherwise, the user can continue to send body data via the request.write()
method, in which case the user will eventually need to call request.end()
to end the request.The connection will been close automatically after getting the response.
Example
Synchronization
- Default GET request:
var http = require('http'); var iosched = require('iosched'); var req = http.request('http://192.168.7.32:8000/index', function(res) { res.on('data', (chunk) => { console.log('get recv data:', chunk.toString()); }); });
- POST request, options set post data:
var req = http.request('http://192.168.7.32:8000/index', function(res) { res.on('data', (chunk) => { console.log('get recv data:', chunk.toString()); }); }, {method: 'POST', post: {id:123, name:'abc'}});
- POST request, req write post data:
var req = http.request('http://192.168.7.32:8000/index', function(res) { res.on('data', (chunk) => { console.log('get recv data:', chunk.toString()); }); }, {method: 'POST'}); if (req) { req.write({id:123, name:'abc'}); // or req.end({id:123, name:'abc'}); req.end(); }
Asynchronous
http.request('http://192.168.7.32:8000/index', function(res) {
res.on('data', (chunk) => {
console.log('get recv data:', chunk.toString());
});
}, {method: 'POST', async: true}
).then((req) => {
req.write({id:123, name:'abc'}); // or req.end({id:123, name:'abc'});
req.end();
}).catch((err) => {
console.error(err.message);
});
You can use the following methods to get the response object:
var req = http.request('http://192.168.7.32:8000', { method: 'GET' });
req.on('response', res => {
res.on('data', (chunk) => {
console.log('get recv data:', chunk.toString());
});
});
The http client res
object inherits from the stream.Readable
object, if you want to ignore the data of the res
object, you can call res.resume
.
var req = http.request('http://192.168.7.32:8000/index', function(res) {
res.resume();
res.on('end', () => {
console.log('Reached the end, but did not read anything.');
});
});
http.get(url[, callback][, options[, tlsOpt]])
url
{String} Http url.callback
{Function} Reuqest handler.res
{HttpClientResponse} Response object.
options
{Object} Has the following properties:domain
{socket.AF_INET | socket.AF_INET6} If the url host is provided as a domain name, the domain name is resolved to an ipv4 or ipv6 address based on the domain.default: socket.AF_INET.saddr
{Object} Server socket address. default: Use url parameter resolution, if you request the same domain name multiple times, it is recommended to set this parameter after manual domain name resolution to speed up the request.path
{String} The request uri path, default: url parsed path.timeout
{Integer} The request timeout (ms). If the request times out,HttpClient
will close. default: 10000.headers
{Object} Http headers. header key must be lowercase.host
{String} The domain name or IP address of the server to which the request is sent. default: url host.async
{Boolean} true - returnPromise
object; false - return client object,default: false
tlsOpt
{Object} TLS securely connections options. default: undefined, means use TCP.- Returns: {HttpClient | Promise} The http client request object or promise object.depend on
async
option.
Accepts the same options as http.request()
, with the method always set to GET
.
Since most requests are GET
requests without bodies, http provides this convenience method. The only difference between this method and http.request()
is that it sets the method to GET
and calls request.end()
automatically.
Example
Synchronization
- GET request:
var req = http.get('http://192.168.7.32:8000/index', function(res) { res.on('data', (chunk) => { console.log('get recv data:', chunk.toString()); }); });
- Query path:
var req = http.get('http://192.168.7.32:8000', function(res) { res.on('data', (chunk) => { console.log('get recv data:', chunk.toString()); }); }, {path: '/index?id=123&name=abc'});
Asynchronous
var promise = http.get('http://192.168.7.32:8000', function(res) {
res.on('data', (chunk) => {
console.log('get recv data:', chunk.toString());
});
}, {path: '/index?id=123&name=abc', async: true});
You can use the following methods to get the response object:
var req = http.get('http://192.168.7.32:8000');
req.on('response', res => {
res.on('data', (chunk) => {
console.log('get recv data:', chunk.toString());
});
});
http.fetch(url[, options])
url
{String} Http url.options
{Object} Has the following properties:method
{String} Http method, default: GET.timeout
{Integer} The request timeout (ms). If the request times out,HttpClient
will close. default: 10000.headers
{Object} Http headers. header key must be lowercase.redirect
{String} How to handle redirect:'follow'
,'error'
,'manual'
, default:'follow'
.body
{String | Buffer | Object | Readable} The request post data, default: undefined.tlsOpt
{Object} TLS securely connections options. default: undefined, means use TCP connection.
- Returns: {Promise} A promise object which then follows
res
object, see: HttpClientResponse.
This is a fetch
style implementation of the http.request
interface, all processing will be done in the promise
object it returns. EdgerOS 1.7.3 and later supports this function.
The http body data can be set in the options.body
. If the options.method
is set to 'GET'
, the body
data will not be sent. You can also pipe a stream body data by pass a Readable
object in options.body
.
A res
object followed promise then,and you can access the response data through the res
object. HttpClientResponse
provides a set of promise
style interfaces for getting response data (detail to see HttpClientResponse):
res.buffer()
res.text()
res.json()
res.pipeTo(writStream)
Example
- GET
http.fetch('http://192.168.128.1:3300/get')
.then((res) => {
return res.text();
})
.then((txt) => {
console.log('fetch msg:', txt);
})
.catch((err) => {
console.error(err);
});
- POST
http.fetch('http://192.168.128.1:3300/post', {
method: "POST",
body: { desc: 'hello' }
})
.then((res) => {
return res.json();
})
.then((obj) => {
console.log('recv result:', obj.result);
})
.catch((err) => {
console.error(err);
});
- POST
Readable
stream
http.fetch('http://192.168.128.1:3300/upload', {
method: "POST",
body: require('fs').createReadStream('./test.jpg')
})
.then((res) => {
if (res.statusCode === 200) {
console.log('Upload success.');
} else {
throw new Error('Upload fail:' + res.statusCode);
}
})
.catch((err) => {
console.error(err);
});
- Pipe to
Writable
stream
http.fetch('http://192.168.128.1:3300/load', {
method: "GET",
})
.then((res) => {
var wStream = require('fs').createWriteStream('./test.mp4');
return res.pipeTo(wStream);
})
.then((res) => {
console.log('Load file success.');
})
.catch((err) => {
console.error(err);
});
HttpClient Object
HttpClient
inherit from HttpOutput
, see the HttpOutput module for details.
client.open([timeout][, async])
timeout
{Integer} Connect timeout(ms), If the request times out,HttpClient
will close. default: 5000.async
{Boolean} true - returnPromise
object; false - return client object,default: false- Returns: {HttpClient | Promise} The http client request object or promise object.depend on
async
param.
Example
- Synchronization
var req = new http.HttpClient(callback, saddr, tlsOpt);
req.on('finish', function() {
req.close();
});
req.on('aborted', function() {
req.close();
});
if (req !== req.open(5000)) {
return undefined;
}
- Asynchronous
var req = new http.HttpClient(callback, saddr, tlsOpt);
req.on('finish', function() {
req.close();
});
req.on('aborted', function() {
req.close();
});
req.open(true)
.then((req) => {
// req.request()
})
.catch((e) => {
console.error(e.message);
});
client.close()
Close http connection, the same as client.destroy()
.
client.request(options[, chunk])
options
{Object} Has the following properties:method
{String} Http method, default: GET.path
{String} The request uri path, default: /.timeout
{Integer} The request timeout (ms). If the request times out,HttpClient
will close. default: 10000.headers
{Object} Http headers. header key must be lowercase.host
{String} The domain name or IP address of the server to which the request is sent. default: IP address.forbidAutoEnd
{Object} Forbid auto end. default: false.
chunk
{String | Buffer} The request post data, default: undefined.
Send a request to the http server, this request method can be GET
, PUT
, POST
... This function will not be blocked, when the server responds, the callback
function will be called.
Example
function cb(res) {
// ...
}
var req = new http.HttpClient(cb, saddr, tlsOpt);
req.on('finish', function() {
req.close();
});
req.on('aborted', function() {
req.close();
});
if (req !== req.open(5000)) {
return undefined;
}
req.request({ method: 'POST', path: '/api/test', timeout: 3000 }, { data: '123' });
client.write(chunk)
chunk
{String | Number | Boolean | Object | Buffer} Http body data.
This method inherit to HttpOutput
. Send data to server. If Content-Length
not set, client.write()
set 'Transfer-Encoding' to 'chunked', and this method can call multiple times. After write all data, user should call client.end()
to end request.
client.end([chunk])
chunk
{String | Number | Boolean | Object | Buffer} Http post data. default: undefined.
This method inherit to HttpOutput
. If chunk
is not empty, the chunk
is sent to the server and the request is ended. After the request is finished, continuing to send data is invalid.
The client automatically sets the Content-Type
header entry based on the chunk type. Content-Type
is set as follows:
Chunk Type | Content-Type |
---|---|
String | text/plain |
Number, Boolean, Object | application/json |
Buffer | application/octet-stream |
client.destroy([error])
error
{Error} which will be passed as payload in'error'
event.- Returns: {HttpClient} This object.
When this method closes the writable
stream, it also closes the underlying socket connection.
HttpClient Events
response
A response
event is emitted when the http response is coming. It has a res
properties:
res
{HttpClientResponse} Http response object.
end
A end
event is emitted when the request had been send. The follow method will emitted 'end' event:
client.end()
close
A close
event is emitted when the client disconnected.
error
A error
event is emitted when the client occur error.It has a err
properties:
err
{Error}err
instanceofError
object.
HttpClientResponse Object
When http.get()
, http.request()
is called, the HttpClientResponse
object is passed as a parameter to the response callback function. The response data can be accessed via the HttpClientResponse
object.
HttpClientResponse
inherit from HttpInput
, see the HttpInput module for more details.
The HttpClientResponse
object specifically provides a set of promise
style interfaces when calling http.fetch()
. Details as follow:
res.buffer()
- Returns: {Promise} A promise object which then follows {Buffer | null} object.
Get response body buffer.
Example
http.fetch('https://192.168.128.1:3300')
.then((res) => {
return res.buffer();
})
.then((buf) => {
console.log('fetch msg:', buf.toString());
})
.catch((err) => {
console.error(err);
});
res.text()
- Returns: {Promise} A promise object which then follows {String} object.
Get response body text.
Example
http.fetch('https://192.168.128.1:3300')
.then((res) => {
return res.text();
})
.then((txt) => {
console.log('fetch msg:', txt);
})
.catch((err) => {
console.error(err);
});
res.json()
- Returns: {Promise} A promise object which then follows a object or
null
.
Get response body json object.
Example
http.fetch('https://192.168.128.1:3300')
.then((res) => {
return res.json();
})
.then((obj) => {
console.log('fetch msg:', obj.id);
})
.catch((err) => {
console.error(err);
});
res.pipeTo(writStream)
writStream
{Writable} Writable stream object.- Returns: {Promise} A promise object which then follows this
res
object.
Pipe response stream to a writable stream. Example to see: Pipe to Writable
stream.
HttpClientResponse Events
data
When HTTP body is received from the server a data
event is emitted with a buf
object:
buf
{Buffer} Receive from from.
end
When all body data is received or there is no body data a end
event is emitted.
Example
- Get
var http = require('http');
var iosched = require('iosched');
http.get('http://192.168.7.32:8000/file/index.json', (res) => {
var statusCode = res.statusCode;
var contentType = res.headers['content-type'];
var error = null;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' + `Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n'
+ `Expected application/json but received ${contentType}`);
}
if (error) {
console.error(error.message);
return;
}
var rawData = '';
res.on('data', (chunk) => {
rawData += chunk.toString();
});
res.on('end', () => {
try {
var parsedData = JSON.parse(rawData);
console.log(parsedData);
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Request error: ${e.message}`);
});
while(true) {
iosched.poll();
}
- Reqeust
var http = require('http');
var iosched = require('iosched');
http.request('http://192.168.7.32:8000/get', function (res) {
console.tag(module, 'GET /get');
res.enableCache();
res.on('end', () => {
console.log('get recv data:', res.body.toString());
});
}).on('error', (e) => {
console.error(`Request error: ${e.message}`);
});
http.request('http://192.168.7.32:8000/json', function (res) {
console.tag(module, 'POST /json');
res.enableCache();
res.on('end', () => {
console.log('get recv data:', res.body.toString());
});
}, { method: 'POST', post: { id: 123, name: 'abc' } })
.on('error', (e) => {
console.error(`Request error: ${e.message}`);
});
http.request('http://192.168.7.32:8000/text', function (res) {
console.tag(module, 'POST /text');
res.enableCache();
res.on('end', () => {
console.log('get recv data:', res.body.toString());
});
}, { method: 'POST', post: `{id:123, name:'abc'}` })
.on('error', (e) => {
console.error(`Request error: ${e.message}`);
});
var req = http.request('http://192.168.7.32:8000/raw', function (res) {
console.tag(module, 'POST /raw');
res.enableCache();
res.on('end', () => {
console.log('get recv data:', res.body.toString());
});
}, { method: 'POST' })
.on('error', (e) => {
console.error(`Request error: ${e.message}`);
});
if (req) {
req.end(Buffer.alloc('This is a buffer.'));
}
var req2 = http.request('http://192.168.7.32:8000/urlencoded', function (res) {
console.tag(module, 'POST /urlencoded');
res.enableCache();
res.on('end', () => {
console.log('get recv data:', res.body.toString());
});
}, { method: 'POST' })
.on('error', (e) => {
console.error(`Request error: ${e.message}`);
});
if (req2) {
req2.setHeader('Content-Type', 'application/x-www-form-urlencoded');
req2.end('id=13&name=ling');
}
while (true) {
iosched.poll();
}