node.js获取php curl post数据req.body为空的处理

node使用了express4和body-parser来解析php curl的数据,但是获取的req.body是{},设置了header

前提知识:

body-parser不支持解析multi/form-data的功能,如果是传递二进制数据或者文件上传,就不能用它了。

Node.js body parsing middleware.

This does not handle multipart bodies, due to their complex and typically large nature. For multipart bodies, you may be interested in the following modules:

busboy and connect-busboy
multiparty and connect-multiparty
formidable
multer
This module provides the following parsers:

JSON body parser
Raw body parser
Text body parser
URL-encoded form body parser

参考:
https://github.com/expressjs/body-parser#bodyparserurlencodedoptions

PHP 代码
function addCurl($url, $type="get", $postData=null)
	{
		$ch = curl_init();
		$headers[] = 'Connection: Keep-Alive';
		$headres[] = 'Content-Type: application/x-www-form-urlencoded;charset=utf-8';		
		$headers[] = 'Content-Length: ' . strlen(json_encode($postData));
		//$headres[] = 'Content-Type: application/json';
		//$headres[] = 'Content-Type: text/html';
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		if ($type=="get") {
			curl_setopt($ch, CURLOPT_POST, 0);
		} else {
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, urlencode(json_encode($postData)));
		}
		curl_setopt($ch, CURLOPT_URL, $url);
		$data = curl_exec($ch);
		$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		
		if (curl_errno($ch)) {
			echo 'Curl error: ' . curl_error($ch) . PHP_EOL;
			curl_close($ch);
			return false;
		} 
		curl_close($ch);
		return ($code == 200) ? $data : "server error,code: . {$code}";
	}


node 代码
var express = require('express')
var bodyParser = require('body-parser')

var app = express()
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.use(urlencodedParser, function (req, res) {
  res.setHeader('Content-Type', 'text/plain')
  res.write('you posted:\n')
  res.end(JSON.stringify(req.body, null, 2))
})

app.listen(3000, function() {
	console.log('Server is running')
})


指定了解析方式依然不行。就到body-parser的源码中一行行调试下去。

找到urlencode.js
// determine if request should be parsed
    if (!shouldParse(req)) {
      return ('skip parsing'), next()
    }


这行shouldParse 返回false
再到type-is.js/index.js 返回false。
var value = req.headers['content-type']


function typeofrequest(req, types_) {
  var types = types_
  // no body
  if (!hasbody(req)) {
    return null
  }

  // support flattened arguments
  if (arguments.length > 2) {
    types = new Array(arguments.length - 1)
    for (var i = 0; i < types.length; i++) {
      types[i] = arguments[i + 1]
    }
  }
  // request content type
  var value = req.headers['content-type']
  return typeis(value, types)
}


发现这里的req.headers['content-type'] 是 multipart/form-data,而type是application/x-www-form-urlencoded

原来,在php执行curl的时候,postData是数组,会将数据编码设置为 multipart/form-data

Note:
传递一个数组到CURLOPT_POSTFIELDS,cURL会把数据编码成 multipart/form-data,而然传递一个URL-encoded字符串时,数据会被编码成 application/x-www-form-urlencoded。


修改pHP代码

curl_setopt($ch, CURLOPT_POSTFIELDS, urlencode(json_encode($postData)));




参考:
http://php.net/manual/zh/function.curl-setopt.php

猜你喜欢

转载自lhdst-163-com.iteye.com/blog/2245236