Request是一个Node.jsNPM模块,它是一个HTTP客户端,使用简单功能确十分强大。我们可以用它来实现HTTP响应流的转接、模拟Form表单提交、支持HTTP认证、OAuth登录、自定义请求头等。下面我们来对这个模块做一个完整的介绍:
1. 安装及简单使用
安装request模块:
npm install request</div>
Request设计为用最简单的方法发送HTTP请求,它还支持HTTPS请求和自动重定向跟踪:
var request = require('request'); request('http://www.baidu.com', function (error, response, body) { if (!error && response.statusCode == 200) { console.log(body) // IT笔录主页的HTML } })</div>
引用request模块后,就可以能通过request()方法来发送HTTP请求,在不指定请求选项option时,默认为GET。在上面请求中,对URLhttp://www.baidu.com
会301重定向到http://www.baidu.com。而Request会自动跟踪URL重定向请求,默认支持10次重定向跟踪。
2. 流(stream)操作
Node.js原生HTTP模块实现了对HTTP请求和响应对象的流操作,Request同样支持基于流的操作。
如,可以将任何响应流通过pipe转接到一个文件流:
request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
</div>
同样,可以将一个读取的文件流转接到PUT或POST请求中。这个方法会自动检查文件扩展名,并设置一个与文件扩展名对应的content-type(当该请求头未设置时):
fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
</div>
Request也支持pipe到它自己。这样操作时,content-type和content-length将被传递到其后的PUT请求中:
request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
</div>
与原生HTTP客户端一样,Request在收到请求响应时会发送一个'response'。事件回调函数中会包含一个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'))</div>
当请求发生错误时,可以简单的通过监听error事件来处理:
request .get('http://mysite.com/doodle.png') .on('error', function(err) { console.log(err) }) .pipe(fs.createWriteStream('doodle.png'))</div>
发挥一个想象:
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) } } })</div>
也可以使用pipe()方法将一个http.ServerRequest实例转换到一个http.ServerResponse。HTTP请求方法、请求头、请求体数据会被发送:
http.createServer(function (req, resp) { if (req.url === '/doodle.png') { var x = request('http://mysite.com/doodle.png') req.pipe(x) x.pipe(resp) } })</div>
通过pipe()返回的目标流,在Nodev0.5.x+版本中,可以写到一行:
req.pipe(request('http://mysite.com/doodle.png')).pipe(resp)
</div>
而所有这些,没有一个新功能会与原功能有冲突,只是对其进行了扩展。还可以使用HTTP代理,请求会被自动重定向并跟踪:
var 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) } })</div>
3. Form表单
request支付application/x-www-form-urlencoded 和 multipart/form-data 编码的form 上传。multipart/related会引用multipartAPI。
application/x-www-form-urlencoded (URL编码的Form)
URL编码的Form很简单:
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){ /* ... */ })</div>
multipart/form-data (Multipart Form 上传)
对于multipart/form-dataFrom文件上传,Request使用了form-data处理。大多数情况,可以通过formData选项添加上传文件:
var formData = { // 键-值对简单值 my_field: 'my_value', // 使用 Buffers 添加数据 my_buffer: new Buffer([1, 2, 3]), // 使用 Streams 添加数据 my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), // 通过数组添加 multiple 值 attachments: [ fs.createReadStream(__dirname + '/attachment1.jpg'), fs.createReadStream(__dirname + '/attachment2.jpg') ], // 添加可选的 meta-data 使用: {value: DATA, options: OPTIONS} // 对于一些流类型,需要提供手工添加 "file"-关联 // 详细查看 `form-data` : https://github.com/form-data/form-data custom_file: { value: fs.createReadStream('/dev/urandom'), options: { filename: 'topsecret.jpg', contentType: 'image/jpg' } } }; 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); });</div>
在一些更加高级的使用中,可以通过其自身的如r.form()来访问Form数据:
// NOTE: Advanced use-case, for normal use see 'formData' usage above var r = request.post('http://service.com/upload', function optionalCallback(err, httpResponse, body) {...}) var form = r.form(); form.append('my_field', 'my_value'); form.append('my_buffer', new Buffer([1, 2, 3])); form.append('custom_file', fs.createReadStream(__dirname + '/unicycle.jpg'), {filename: 'unicycle.jpg'});</div>
multipart/related
在一些不同的HTTP实现中,需要在multipart/related的之前、之后或前后同时添加一个newline/CRLF(通过multipart选项)。特别是在.NET WebAPI 4.0中,需要将preambleCRLF设置为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', _attachment