转: Nodejs 发送HTTP POST请求实例

项目里面需要用到使用NodeJs来转发HTTP POST请求,把过程记录一下:

 

  1. exports.sendEmail = function (req, res) {  
  2.     res.send(200, req.body.address);  
  3. }  


之所以能够访问body的address属性,这得益于express.js(connect)的bodyparser中间件。该中间件解析request的body,假如其content type满足某些条件的话,就尝试将其转换成javascript对象。某些条件是指:multipart, urlencoded, json。

 

好了,接下来看转发端的代码,为了简单起见,我直接将hard-coding的数据进行转发:

 

 1 /**
 2  * nodejs向apache发送请求,接收响应后返回到浏览器端
 3  */
 4 app.get('/nodeReq', function(req,res,next){
 5     var data = {
 6         age: 20,
 7         name: "cici",
 8         like: "shopping"
 9     };
10     data = require('querystring').stringify(data); //数据以url param格式发送
11     data = JSON.stringify(data); //数据以json格式发送
12     console.log(data);
13     var opt = {
14         method: "POST",
15         host: "localhost",
16         port: 8012,
17         path: "/php/get_data.php",
18         headers:{
19             //"Content-Type": "application/x-www-form-urlencoded", //for url parameter
20             "Content-Type": "application/json", // for json data
21             "Content-Length": data.length
22         }
23     };
24 
25     var req = http.request(opt, function(apacheRes){//建立连接 和 响应回调
26         if(apacheRes.statusCode == 200){
27             apacheRes.setEncoding('utf8');
28             var body = "";
29             apacheRes.on('data', function(recData){ body += recData;});
30             apacheRes.on('end', function(){ res.send(body); /*发送收到的响应*/ });
31         }else{
32             res.send(500, "error");
33         }
34     });
35     req.write(data + "\n"); //发送请求
36     req.end(); //请求发送完毕
37 });

 

注意,我把content type设置成x-www-form-urlencoded,这是bodyparser所支持的了类型之一,而body的格式通过require('querystring').stringify(...)来格式化的,这个会将对象转换成诸如"address=test%40test.com&subject=test"这种格式的字符串。

另一个是用JSON.stringify()来格式化body内容,然后把content-type改为application/json格式,当然,这个也是body parser所支持的格式之一!

 另外,有两个地方,我不是很清楚,一个是貌似content-length不是必须的,另一个是req.write(data+"\n")的"\n"也不是必须的,这个有待研究。。。

 补充:

bodyparser的代码在”\node_modules\express\node_modules\connect\lib\middleware\bodyParser.js“,它其实什么都没做,只是把解析body的任务派发给了另外3个中间件:./multipart, ./urlencoded, ./json:

 

    • ./multipart 负责 application/x-www-form-urlencoded 类型。
    • ./urlencoded 负责 multipart/form-data 类型。
    • ./json 负责 application/json 类型。

 

 

用http.request发送文件给服务端, 或带参post数据到服务端

var http = require('http');
var fs = require('fs');
var queryString = require('querystring');

var boundaryKey = 'A' + new Date().getTime(); //随便加个前缀A 避免全数字作为分界符

/**
 * 带参数发post请求
 */
function doPost(){
    var opt = {
        host:'localhost', //注意:不用协议部分(http://)
        port:'80',
        path: '/testonly/doupload.php', //斜杠开头
        method:'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'} //设置content-type 头部
    };

    var body = '';
    var req = http.request(opt, function(res){
        res.statusCode == 200 && console.log('REQUEST OK..' );
        res.setEncoding('utf8');//res为ClientResponse的实例,是readableStream, 设置字符编码

        res.on('data', function(chunk){
            body += chunk;
        }).on('end', function(){
            console.log('Got data: ', body);//end事件中 打印全部响应数据
        });
    }).on('error', function(err){
        console.log('error: ', err.message);
    });

    var data = {name:'sindy', age:22};
    var data1 = JSON.stringify(data);
    var data2 = queryString.stringify(data); //注意 querystring.stringify 和 JSON.stringify的区别
    console.log(data1);
    console.log(data2);

    req.write(data2); //req为ClientRequest的实例,是writableStream,写数据到流中
    req.end();//结束请求
}

/**
 * 发送文件给服务器并带上其他表单字段数据
 */
function doUpload(){
    var opt = {
        host:'localhost',
        port:'80',
        path: '/testonly/doupload.php',
        method:'POST',
        headers: {'Content-Type':'multipart/form-data; boundary='+boundaryKey, 'Connection':'keep-alive'} //注意:上传文件时的 content-type 设置
    };

    var body = '';
    var req = http.request(opt, function(res){
        res.statusCode == 200 && console.log('REQUEST OK..' );
        res.setEncoding('utf8');

        res.on('data', function(chunk){
            body += chunk;
        }).on('end', function(){
            console.log('Got data: ', body);//php 返回 $_FILES 和 $_POST的内容给客户端
        });
    }).on('error', function(err){
        console.log('error: ', err.message);
    });


    
    //ClientRequest writableStream 注意:文件字段的分界符
    req.write('--'+boundaryKey+'\r\nContent-Disposition:form-data; name="upfile"; filename="test.zip"\r\nContent-Type:application/x-zip-compressed'); 

    // 1M缓冲
    var fileStream = fs.createReadStream('test.zip', {bufferSize: 1024 * 1024});
    fileStream.pipe(req, {end: false});

    fileStream.on('end', function(){
        // ::注意::文件字段内容和其他字段之间空2行,字段名和字段值之间空2行
        req.write('\r\n\r\n--'+boundaryKey+'\r\n'+'Content-Disposition: form-data; name="submit"\r\n\r\n'+'sendfile');
        req.end('\r\n--'+ boundaryKey + '--'); //注意:结束时的分界符 末尾'--'
    });

    


}

// doPost();

doUpload();

 

posted @ 2014-12-25 13:18  stephenykk  阅读(10205)  评论(1编辑  收藏  举报