请求被设计为进行 http 调用的最简单方法。它支持 HTTPS,默认情况下遵循重定向。
const request = require('request');
request('http://www.google.com', function (error, response, body) {
console.error('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
Request 还提供了诸如 和的 便捷方法,并且有许多 使用示例 和几种 调试技术。request.defaultsrequest.post
您可以将任何响应流到文件流。
request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
您还可以将文件流式传输到 PUT 或 POST 请求。此方法还将根据文件扩展名到内容类型的映射(在这种情况下application/json)检查文件扩展名,并content-type在PUT请求中使用正确的名称(如果标头尚未提供)。
fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
请求也 pipe 可以自己处理。这样做时,content-type 并 content-length 保留在PUT标头中。
request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
收到响应后,请求将发出“响应”事件。该 response 参数将是 http.IncomingMessage 的实例。
request
.get('http://google.com/img.png')
.on('response', function(response) {
console.log(response.statusCode) // 200
console.log(response.headers['content-type']) // 'image/png'
})
.pipe(request.put('http://mysite.com/img.png'))
为了在处理流请求时轻松处理错误,请error在管道传输之前侦听事件:
request
.get('http://mysite.com/doodle.png')
.on('error', function(err) {
console.error(err)
})
.pipe(fs.createWriteStream('doodle.png'))
现在让我们开始幻想。
http.createServer(function (req, resp) {
if (req.url === '/doodle.png') {
if (req.method === 'PUT') {
req.pipe(request.put('http://mysite.com/doodle.png'))
} else if (req.method === 'GET' || req.method === 'HEAD') {
request.get('http://mysite.com/doodle.png').pipe(resp)
}
}
})
您还可以pipe()从http.ServerRequest实例,也可以到http.ServerResponse实例。将发送HTTP方法,标头和实体数据。这意味着,如果您不太在意安全性,则可以执行以下操作:
http.createServer(function (req, resp) {
if (req.url === '/doodle.png') {
const x = request('http://mysite.com/doodle.png')
req.pipe(x)
x.pipe(resp)
}
})
并且由于pipe()返回≥0.5.x节点中的目标流,因此您可以执行一行代理。:)
req.pipe(request('http://mysite.com/doodle.png')).pipe(resp)
而且,这些新功能都不会与请求以前的功能发生冲突,只会扩展它们。
const r = request.defaults({'proxy':'http://localproxy.com'})
http.createServer(function (req, resp) {
if (req.url === '/doodle.png') {
r.get('http://google.com/doodle.png').pipe(resp)
}
})
您仍然可以使用中间代理,请求仍将遵循HTTP转发等。
request 本机支持流和回调接口。如果您想request返回一个Promise,则可以使用替代接口包装request。如果您更喜欢使用Promises,或者您想在ES2017中使用async/ await,这些包装器将非常有用。
请求团队提供了几种替代接口,包括:
另外,util.promisifyNode.js v8.0中提供的可以用来转换一个常规函数,该函数接受回调以返回诺言。
request支持application/x-www-form-urlencoded并multipart/form-data上传表格。有关multipart/related参考multipartAPI。
URL编码的表单很简单。
request.post('http://service.com/upload', {form:{key:'value'}})
// or
request.post('http://service.com/upload').form({key:'value'})
// or
request.post({url:'http://service.com/upload', form: {key:'value'}}, function(err,httpResponse,body){ /* ... */ })
对于multipart/form-data我们使用表单数据的库@felixge。在大多数情况下,您可以通过formData选项传递上传表单数据。
const formData = {
// Pass a simple key-value pair
my_field: 'my_value',
// Pass data via Buffers
my_buffer: Buffer.from([1, 2, 3]),
// Pass data via Streams
my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
// Pass multiple values /w an Array
attachments: [
fs.createReadStream(__dirname + '/attachment1.jpg'),
fs.createReadStream(__dirname + '/attachment2.jpg')
],
// Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS}
// Use case: for some types of streams, you'll need to provide "file"-related information manually.
// See the `form-data` README for more information about options: https://github.com/form-data/form-data
custom_file: {
value: fs.createReadStream('/dev/urandom'),
options: {
filename: 'topsecret.jpg',
contentType: 'image/jpeg'
}
}
};
request.post({url:'http://service.com/upload', formData: formData}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
对于高级情况,您可以通过访问表格数据对象本身r.form()。可以对其进行修改,直到在事件循环的下一个周期触发请求为止。(请注意,此调用form()将清除该请求的当前设置的表单数据。)
//注意:高级用例,对于正常使用,请参见
const r = request.post('http://service.com/upload', function optionalCallback(err, httpResponse, body) {...})
const form = r.form();
form.append('my_field', 'my_value');
form.append('my_buffer', Buffer.from([1, 2, 3]));
form.append('custom_file', fs.createReadStream(__dirname + '/unicycle.jpg'), {filename: 'unicycle.jpg'});
有关更多信息和示例,请参见表单数据自述文件。
不同HTTP实现中的某些变体在multipart/related请求边界之前,之后或之前和之后都需要换行符/ CRLF (使用multipart选项)。在.NET WebAPI 4.0版中已经观察到了这一点。您可以通过将边界preambleCRLF或postamble传递true给您的请求选项来打开它们。
request({
method: 'PUT',
preambleCRLF: true,
postambleCRLF: true,
uri: 'http://service.com/upload',
multipart: [
{
'content-type': 'application/json',
body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
},
{ body: 'I am an attachment' },
{ body: fs.createReadStream('image.png') }
],
// alternatively pass an object containing additional options
multipart: {
chunked: false,
data: [
{
'content-type': 'application/json',
body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
},
{ body: 'I am an attachment' }
]
}
},
function (error, response, body) {
if (error) {
return console.error('upload failed:', error);
}
console.log('Upload successful! Server responded with:', body);
})
request.get('http://some.server.com/').auth('username', 'password', false);
// or
request.get('http://some.server.com/', {
'auth': {
'user': 'username',
'pass': 'password',
'sendImmediately': false
}
});
// or
request.get('http://some.server.com/').auth(null, null, true, 'bearerToken');
// or
request.get('http://some.server.com/', {
'auth': {
'bearer': 'bearerToken'
}
});
如果作为选项传递,auth则应为包含值的哈希值:
方法表格带有参数 auth(username, password, sendImmediately, bearer)。
sendImmediately默认为true,这将导致发送基本或承载身份验证标头。如果sendImmediately为false,则request在接收401到服务器的响应(必须包含WWW-Authenticate指示所需认证方法的标头)后, 将使用适当的认证标头重试 。
请注意,您还可以使用URL本身指定基本身份验证,如RFC 1738中所述。只需 user:password在主持人之前通过@标志:
const username = 'username',
password = 'password',
url = 'http://' + username + ':' + password + '@some.server.com';
request({url}, function (error, response, body) {
// Do more stuff with 'body' here
});
支持摘要式身份验证,但仅sendImmediately 将设置为false;否则,request将在初始请求上发送基本身份验证,这可能会导致请求失败。
支持承载身份验证,并在该bearer值可用时激活。该值可以是a String或Function返回a String。如果与defaults允许单个功能在发送请求时提供最后一个已知令牌或即时计算一个令牌一起使用,则使用函数提供承载令牌特别有用。
User-Agent可以在options对象中设置HTTP标头(例如)。在下面的示例中,我们调用github API来查找请求存储库的星号和分叉数。这需要一个自定义User-Agent标头以及https。
const request = require('request');
const options = {
url: 'https://api.github.com/repos/request/request',
headers: {
'User-Agent': 'request'
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
const info = JSON.parse(body);
console.log(info.stargazers_count + " Stars");
console.log(info.forks_count + " Forks");
}
}
request(options, callback);
支持OAuth 1.0版。默认签名算法为 HMAC-SHA1:
// OAuth1.0 - 3-legged server side flow (Twitter example)
// step 1
const qs = require('querystring')
, oauth =
{ callback: 'http://mysite.com/callback/'
, consumer_key: CONSUMER_KEY
, consumer_secret: CONSUMER_SECRET
}
, url = 'https://api.twitter.com/oauth/request_token'
;
request.post({url:url, oauth:oauth}, function (e, r, body) {
// Ideally, you would take the body in the response
// and construct a URL that a user clicks on (like a sign in button).
// The verifier is only available in the response after a user has
// verified with twitter that they are authorizing your app.
// step 2
const req_data = qs.parse(body)
const uri = 'https://api.twitter.com/oauth/authenticate'
+ '?' + qs.stringify({oauth_token: req_data.oauth_token})
// redirect the user to the authorize uri
// step 3
// after the user is redirected back to your server
const auth_data = qs.parse(body)
, oauth =
{ consumer_key: CONSUMER_KEY
, consumer_secret: CONSUMER_SECRET
, token: auth_data.oauth_token
, token_secret: req_data.oauth_token_secret
, verifier: auth_data.oauth_verifier
}
, url = 'https://api.twitter.com/oauth/access_token'
;
request.post({url:url, oauth:oauth}, function (e, r, body) {
// ready to make signed requests on behalf of the user
const perm_data = qs.parse(body)
, oauth =
{ consumer_key: CONSUMER_KEY
, consumer_secret: CONSUMER_SECRET
, token: perm_data.oauth_token
, token_secret: perm_data.oauth_token_secret
}
, url = 'https://api.twitter.com/1.1/users/show.json'
, qs =
{ screen_name: perm_data.screen_name
, user_id: perm_data.user_id
}
;
request.get({url:url, oauth:oauth, qs:qs, json:true}, function (e, r, user) {
console.log(user)
})
})
})
对于RSA-SHA1签名,请对OAuth选项对象进行以下更改:
对于PLAINTEXT签名,请对OAuth选项对象进行以下更改:
如 oauth1规范的“ 使用者请求参数”部分所述,通过查询参数或在帖子正文中发送OAuth参数 :
要使用请求正文哈希,您可以
如果您指定一个proxy选项,那么请求(以及所有后续重定向)将通过连接发送到代理服务器。
如果您的端点是一个httpsURL,并且使用的是代理服务器,然后请求将发送CONNECT到代理服务器的请求,第一,然后使用附带的连接来连接到端点。
也就是说,首先它将发出如下请求:
HTTP/1.1 CONNECT endpoint-server.com:80
Host: proxy-server.com
User-Agent: whatever user agent you specify
然后代理服务器endpoint-server 在端口上建立与TCP的连接80,并返回如下响应:
HTTP/1.1 200 OK
此时,连接保持打开状态,客户端直接与endpoint-server.com机器通信。
有关 更多信息,请参见HTTP隧道上的Wikipedia页面。
默认情况下,代理http流量时,请求将仅发出标准代理http请求。这是通过使url 请求的初始行部分成为终结点的完全限定的url来完成的。
例如,它将发出一个类似于以下内容的请求:
HTTP/1.1 GET http://endpoint-server.com/some-url
Host: proxy-server.com
Other-Headers: all go here
request body or whatever
因为纯的“ http over http”隧道不提供其他安全性或其他功能,所以在这种情况下,使用简单的HTTP代理通常更简单。但是,如果您想强制使用隧道代理,可以将tunnel选项设置为true。
您也可以http通过显式设置发出标准代理请求 tunnel : false,但是请注意,这将使代理可以查看到/来自目标服务器的流量。
如果您使用的是隧道代理,则可以将设置为 proxyHeaderWhiteList与代理共享某些标头。
您还可以将设置为proxyHeaderExclusiveList仅与代理而不与目标主机共享某些标头。
默认情况下,此设置为:
accept
accept-charset
accept-encoding
accept-language
accept-ranges
cache-control
content-encoding
content-language
content-length
content-location
content-md5
content-range
content-type
connection
date
expect
max-forwards
pragma
proxy-authorization
referer
te
transfer-encoding
user-agent
via
请注意,使用隧道代理时,proxy-authorization 标头和来自custom的任何标头proxyHeaderExclusiveList都 不会发送到终结点服务器,而只会发送到代理服务器。
遵守以下环境变量request:
当HTTP_PROXY/ http_proxy设置,它们将被用于没有一个明确的代理非SSL请求proxy配置选项存在。同样,对于没有显式配置选项的SSL请求,将使用HTTPS_PROXY/ 。在一个环境变量中定义一个代理是有效的,但是使用配置选项针对特定请求覆盖它。此外,可以将配置选项显式设置为false / null,以完全退出该请求的代理。https_proxyproxyproxyproxy
request也知道NO_PROXY/ no_proxy环境变量。这些变量为每个主机提供了一种选择退出代理的精细方法。它应包含逗号分隔的主机列表,以选择退出代理。当使用特定的目标端口时,也可以选择代理。最后,可以将变量设置为*选择退出其他环境变量的隐式代理配置。
以下是有效值的一些示例no_proxy:
request支持向UNIX域套接字发出请求。要制作一个,请使用以下URL方案:
/* Pattern */ 'http://unix:SOCKET:PATH'
/* Example */ request.get('http://unix:/absolute/path/to/unix.socket:/request/path')
注意:SOCKET假定该路径对于主机文件系统的根目录是绝对的。
TLS / SSL协议选项,例如cert,key和passphrase,可直接在设置options对象,在agentOptions所述的属性options对象,或甚至在https.globalAgent.options。请记住,尽管agentOptions允许的配置范围稍微宽一些,但建议的方法是options直接通过对象,因为在代理环境中使用agentOptions或https.globalAgent.options不会以相同的方式应用对象(因为数据通过TLS连接而不是通过http /传输) https代理)。
const fs = require('fs')
, path = require('path')
, certFile = path.resolve(__dirname, 'ssl/client.crt')
, keyFile = path.resolve(__dirname, 'ssl/client.key')
, caFile = path.resolve(__dirname, 'ssl/ca.cert.pem')
, request = require('request');
const options = {
url: 'https://api.some-server.com/',
cert: fs.readFileSync(certFile),
key: fs.readFileSync(keyFile),
passphrase: 'password',
ca: fs.readFileSync(caFile)
};
request.get(options);
在下面的示例中,我们调用需要客户端SSL证书(PEM格式)和密码保护的私钥(PEM格式)的API,并禁用SSLv3协议:
const fs = require('fs')
, path = require('path')
, certFile = path.resolve(__dirname, 'ssl/client.crt')
, keyFile = path.resolve(__dirname, 'ssl/client.key')
, request = require('request');
const options = {
url: 'https://api.some-server.com/',
agentOptions: {
cert: fs.readFileSync(certFile),
key: fs.readFileSync(keyFile),
// Or use `pfx` property replacing `cert` and `key` when using private key, certificate and CA certs in PFX or PKCS12 format:
// pfx: fs.readFileSync(pfxFilePath),
passphrase: 'password',
securityOptions: 'SSL_OP_NO_SSLv3'
}
};
request.get(options);
只能通过指定secureProtocol以下命令来强制使用SSLv3 :
request.get({
url: 'https://api.some-server.com/',
agentOptions: {
secureProtocol: 'SSLv3_method'
}
});
除了通常允许的证书颁发机构(CA)签名的证书之外,还可以接受其他证书。例如,在使用自签名证书时,这可能很有用。要必须有不同的根证书,您可以通过添加CA的证书文件的内容到指定签名CA agentOptions。域提供的证书必须由指定的根证书签名:
request.get({
url: 'https://api.some-server.com/',
agentOptions: {
ca: fs.readFileSync('ca.cert.pem')
}
});
ca如果您具有私有或内部公司公钥基础结构层次结构,则该值可以是证书的数组。例如,如果您要连接到https://api.some-server.com,它会显示一个包含以下内容的钥匙链:
您可以按以下方式配置您的请求:
request.get({
url: 'https://api.some-server.com/',
agentOptions: {
ca: [
fs.readFileSync('Corp Issuing Server.pem'),
fs.readFileSync('Corp Root CA.pem')
]
}
});
该options.har属性将覆盖值:url,method,qs,headers,form,formData,body,json,以及构建多部分数据,并且当从磁盘读取的文件request.postData.params[].fileName的存在而没有匹配value。
验证步骤将检查HAR请求格式是否与最新规范(v1.2)匹配,如果不匹配则跳过解析。
const request = require('request')
request({
// will be ignored
method: 'GET',
uri: 'http://www.google.com',
// HTTP Archive Request Object
har: {
url: 'http://www.mockbin.com/har',
method: 'POST',
headers: [
{
name: 'content-type',
value: 'application/x-www-form-urlencoded'
}
],
postData: {
mimeType: 'application/x-www-form-urlencoded',
params: [
{
name: 'foo',
value: 'bar'
},
{
name: 'hello',
value: 'world'
}
]
}
}
})
// POST请求将发送到http://www.mockbin.com
//正文为 application/x-www-form-urlencoded 正文:
// foo = bar&hello = world
第一个参数可以是a url或options对象。唯一需要的选项是uri;其他所有都是可选的。
callback参数获得3个参数:
还有用于不同HTTP方法的速记方法和其他一些便利。
此方法返回围绕普通请求API 的包装,该包装默认为您传递给它的任何选项。
注意: request.defaults() 不修改全局请求API;而是返回一个包装器,该包装器已应用了您的默认设置。
注意:您可以调用.defaults()从返回的包装器 request.defaults来添加/覆盖以前默认的默认值。
例如:
//requests using baseRequest() will set the 'x-token' header
const baseRequest = request.defaults({
headers: {'x-token': 'my-token'}
})
//requests using specialRequest() will include the 'x-token' header set in
//baseRequest and will also include the 'special' header
const specialRequest = baseRequest.defaults({
headers: {special: 'special value'}
})
这些HTTP方法便利功能的作用类似于,request()但已为您设置了默认方法:
创建新cookie的函数。
request.cookie('key1=value1')
创建新的Cookie罐的函数。
request.jar()
使用不区分大小写的匹配返回指定的响应头字段的函数
request('http://www.google.com', function (error, response, body) {
// print the Content-Type header even if the server returned it as 'content-type' (lowercase)
console.log('Content-Type is:', response.caseless.get('Content-Type'));
});
至少有三种方法可以调试以下各项的操作request:
如果服务器没有及时响应,则对外部服务器的大多数请求都应附加超时。如果没有超时,您的代码可能会在几分钟或更长时间内打开/使用套接字资源。
超时主要有两种类型:连接超时和读取超时。如果在客户端尝试建立与远程计算机的连接时发生超时,则发生连接超时(对应于 套接字上的connect()调用)。每当服务器太慢而无法发回一部分响应时,就会发生读取超时。
这两种情况对请求出了什么问题的含义有很大不同,因此区分它们是很有用的。您可以通过检查err.code“ ETIMEDOUT”值来检测超时错误。此外,您可以通过检查err.connect属性是否设置为来检测超时是否是连接超时 true。
request.get('http://10.255.255.1', {timeout: 1500}, function(err) {
console.log(err.code === 'ETIMEDOUT');
// Set to `true` if the timeout was a connection timeout, `false` or
// `undefined` otherwise.
console.log(err.connect === true);
process.exit(0);
});
const request = require('request')
, rand = Math.floor(Math.random()*100000000).toString()
;
request(
{ method: 'PUT'
, uri: 'http://mikeal.iriscouch.com/testjs/' + rand
, multipart:
[ { 'content-type': 'application/json'
, body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}})
}
, { body: 'I am an attachment' }
]
}
, function (error, response, body) {
if(response.statusCode == 201){
console.log('document saved as: http://mikeal.iriscouch.com/testjs/'+ rand)
} else {
console.log('error: '+ response.statusCode)
console.log(body)
}
}
)
为了向后兼容,默认情况下不支持响应压缩。要接受gzip压缩的响应,请将gzip选项设置为true。请注意,在request未修改响应对象的情况下,传递的正文数据将自动解压缩,并且如果服务器发送了压缩的响应,则将包含压缩的数据。
const request = require('request')
request(
{ method: 'GET'
, uri: 'http://www.google.com'
, gzip: true
}
, function (error, response, body) {
// body is the decompressed response body
console.log('server encoded the data as: ' + (response.headers['content-encoding'] || 'identity'))
console.log('the decoded data is: ' + body)
}
)
.on('data', function(data) {
// decompressed data as it is received
console.log('decoded chunk: ' + data)
})
.on('response', function(response) {
// unmodified http.IncomingMessage object
response.on('data', function(data) {
// compressed data as it is received
console.log('received ' + data.length + ' bytes of compressed data')
})
})
Cookies默认是禁用的(否则,它们将在后续请求中使用)。要启用cookie,请设置jar为true(中的defaults或options)。
const request = request.defaults({jar: true})
request('http://www.google.com', function () {
request('http://images.google.com')
})
要使用自定义Cookie罐(而不是request的全局Cookie罐),请设置jar为的实例request.jar()(位于defaults或中options)
const j = request.jar()
const request = request.defaults({jar:j})
request('http://www.google.com', function () {
request('http://images.google.com')
})
或者
const j = request.jar();
const cookie = request.cookie('key1=value1');
const url = 'http://www.google.com';
j.setCookie(cookie, url);
request({url: url, jar: j}, function () {
request('http://images.google.com')
})
要使用自定义 Cookie 存储(例如 FileCookieStore 支持保存到JSON文件和从JSON文件还原的Cookie存储 ),请将其作为参数传递给request.jar():
const FileCookieStore = require('tough-cookie-filestore');
// NOTE - currently the 'cookies.json' file must already exist!
const j = request.jar(new FileCookieStore('cookies.json'));
request = request.defaults({ jar : j })
request('http://www.google.com', function() {
request('http://images.google.com')
})
Cookie 存储必须是一个 tough-cookie 存储,并且必须支持同步操作。 有关详细信息,请参见 CookieStoreAPI 文档。
在请求后检查饼干罐:
const j = request.jar()
request({url: 'http://www.google.com', jar: j}, function () {
const cookie_string = j.getCookieString(url); // "key1=value1; key2=value2; ..."
const cookies = j.getCookies(url);
// [{key: 'key1', value: 'value1', domain: "www.google.com", ...}, ...]
})

