Web服务通过curl命令行工作,但不通过PHP


Webservice works through curl command line but not PHP

我正在尝试将收到的curl命令转换为可以通过PHP运行的命令。

命令是:

curl -F customerid=902 -F username=API1 -F password=somepassword -F reportname=1002 http://somerandomurl.com/api/v1/getreportcsv

然而,当我尝试通过PHP(并最终通过C#)运行它时,web服务会返回一个错误。你知道我的代码可能出了什么问题吗?我认为web服务必须非常具体地说明标题/请求:

$url = "http://somerandomurl.com/api/v1/getreportcsv";
$fields = [
  "customerid" => "902",
  "username"   => "API1",
  "password"   => "somepassword",
  "reportname" => "1002"
];
$fields_string = "";
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
//open connection
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
//execute post
$result = curl_exec($ch);
print $result;

Wireshark显示了以下差异:

以下是有效的:

POST /somefolder/api/v1/getreportcsv HTTP/1.1
Host: somehost
Accept: */*
Content-Length: 65
Content-Type: application/x-www-form-urlencoded
customerid=902&username=API1&password=somepassword&reportname=1002&HTTP/1.1 200 OK
Server: GlassFish Server Open Source Edition 3.1.1
Content-Type: text/html;charset=UTF-8
Content-Length: 6
Date: Thu, 26 Nov 2015 22:51:23 GMT
ERROR 

而这个有效:

POST /someurl/api/v1/getreportcsv HTTP/1.1
User-Agent: curl/7.33.0
Host: somehost
Accept: */*
Content-Length: 459
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------4b0d14cc31a40c5b
HTTP/1.1 100 Continue
--------------------------4b0d14cc31a40c5b
Content-Disposition: form-data; name="customerid"
902
--------------------------4b0d14cc31a40c5b
Content-Disposition: form-data; name="username"
API1
--------------------------4b0d14cc31a40c5b
Content-Disposition: form-data; name="password"
somepassword
--------------------------4b0d14cc31a40c5b
Content-Disposition: form-data; name="reportname"
1002
--------------------------4b0d14cc31a40c5b--
HTTP/1.1 200 OK
Server: GlassFish Server Open Source Edition 3.1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 26 Nov 2015 23:13:57 GMT
2000
...snip... the results of the api

很明显,它们是非常不同的请求,但我没想到会有这么具体的请求?

这个问题似乎对所讨论的服务非常具体。

但是,问题可能出在标头上。根据curl手册页:

-F[…]导致curl使用内容类型POST数据根据RFC 2388 的multipart/form-data

但是,根据PHP手册,CURLOPT_POST选项将使用application/x-www-form-urlencoded发送数据。

根据同一手册,如果CURLOPT_POSTFIELDS的值是一个数组,则Content-Type标头将设置为multipart/form-data。您也可以尝试将内容类型显式设置为标头。

尝试设置以下cURL选项:

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: multipart/form-data'));

如果这不起作用,它可能有助于使用-v参数分析命令行curl发送的所有标头,并尝试设置它们。显式设置内容长度标头也是一个好主意。