本文針對版本:Node.js 0.12.4
之前寫過一篇Node.js發送和接收HTTP的GET請求的文章,今天再寫一篇,講發送POST的請求,當然,也是不借助任何外力,使用Node.js原生Module。
發送POST請求,相比GET會有些蛋疼,因為Node.js(目前0.12.4)現在還沒有直接發送POST請求的封裝。發送GET的話,使用http.get可以直接傳一個字符串作為URL,而http.get方法就是封裝原始的http.request方法。發送POST的話,只能使用原始的http.request方法,同時因為要設置HTTP請求頭的參數,所以必須傳入一個對象作為http.request的第一個options參數(而不是URL字符串)。另外,options參數中的hostname需要的是不帶協議的URL根路徑,子路徑需要在path屬性單獨設置。如果hostname包含了完整的URL,通常會遇到錯誤:Error: getaddrinfo ENOTFOUND http://www.xxx.com/xxx。
這里可以使用url Module進行協助,使用url.parse返回值的hostname和path屬性就可以,測試代碼:
var url = require('url');
console.log(url.parse('http://www.mgenware.com/a/b/c'));
輸出:
{ protocol: 'http:',
slashes: true,
auth: null,
host: 'www.mgenware.com',
port: null,
hostname: 'www.mgenware.com',
hash: null,
search: null,
query: null,
pathname: '/a/b/c',
path: '/a/b/c',
href: 'http://www.mgenware.com/a/b/c' }
OK,hostname和path參數解決后,然后就是常見POST請求HTTP Header屬性的設置,設置method為POST,另外如果是模擬HTML <form>的POST請求的話,Content-Type應當是application/x-www-form-urlencoded,最后別忘了Content-Length,而且,如果Content是字符串的話最好用Buffer.byteLength('字符串', 'utf8')來獲取字節長度(而不是直接'字符串'.length,雖然使用URL編碼的ASCII字符串每個字符是1字節)。
然后就是回調的處理,這個在上篇文章中又講過,Callback中的第一個res參數是執行Readable Stream接口的,通過res的data事件來把chunk存在數組里,最后在end事件里使用Buffer.concat把數據轉換成完整的Buffer,需要的話,通過Buffer.toString把Buffer轉換成回應的字符串。
完整代碼(我們使用httpbin.org做POST測試):
var querystring = require('querystring');
var url = require('url');
var http = require('http');
var https = require('https');
var util = require('util');
//POST URL
var urlstr = 'http://httpbin.org/post';
//POST 內容
var bodyQueryStr = {
name: 'mgen',
id: 2345,
str: 'hahahahahhaa'
};
var contentStr = querystring.stringify(bodyQueryStr);
var contentLen = Buffer.byteLength(contentStr, 'utf8');
console.log(util.format('post data: %s, with length: %d', contentStr, contentLen));
var httpModule = urlstr.indexOf('https') === 0 ? https : http;
var urlData = url.parse(urlstr);
//HTTP請求選項
var opt = {
hostname: urlData.hostname,
path: urlData.path,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': contentLen
}
};
//處理事件回調
var req = httpModule.request(opt, function(httpRes) {
var buffers = [];
httpRes.on('data', function(chunk) {
buffers.push(chunk);
});
httpRes.on('end', function(chunk) {
var wholeData = Buffer.concat(buffers);
var dataStr = wholeData.toString('utf8');
console.log('content ' + wholeData);
});
}).on('error', function(err) {
console.log('error ' + err);
});;
//寫入數據,完成發送
req.write(contentStr);
req.end();
運行完畢后,會以字符串輸出HTTP回應內容。
