HTTP 标头"Content-type: multipart/mixed"会导致"400 Bad request"



我正试图使用php的fsockopen将文件上传到远程服务器。如果我的请求看起来像:

$httpContent = [
"POST /index.php HTTP/1.1", 
"Host: The IP address of my remote server", 
"Connection: Close", 
"User-Agent: My client"
];

服务器以CCD_ 1进行响应。但是,如果我添加

"Content-Type: multipart/mixed; boundary=".md5('myBoundary'), 
"--".md5('myBoundary'), 
"Content-Type: text/plain", 
"value", 
"--".md5('myBoundary')."--"

服务器返回"400错误请求"。在我看来一切都很好,但不知怎么的,它不起作用。我做错了什么?

非常感谢您的帮助!

编辑(@Rei建议发布请求转储(:

这就是客户端终端中的回声

POST /index.php HTTP/1.1
Host: The IP address of my remote server
Connection: Close
User-Agent: My client
Content-Type: multipart/mixed; boundary=be0850c82dd4983ddc49a51a797dce49
--be0850c82dd4983ddc49a51a797dce49
Content-Type: text/plain
value
--be0850c82dd4983ddc49a51a797dce49--

这就是服务器得到的(用tcpdump捕获(:

POST /index.php HTTP/1.1
Host: The IP address of my remote server
Connection: Close
User-Agent: My client
Content-Type: multipart/mixed; boundary=be0850c82dd4983ddc49a51a797dce49
--be0850c82dd4983ddc49a51a797dce49
Content-Type: text/plain
value
--be0850c82dd4983ddc49a51a797dce49--

我个人认为两者之间没有任何区别,也不认为请求有任何错误。然而,服务器返回"400错误请求"。

*注意:"我的远程服务器的IP地址"是一个真实的IP地址,但出于安全考虑,我不会发布它。

**注意:没有提到PHP脚本在CLI环境中运行,并且不用作web应用程序后端(请求不是由web浏览器准备的(。

正如我所怀疑的,您发送的HTTP请求不符合HTTP规范。参见RFC7230第3节。问题是:缺少CRLF。

最后一个HTTP标头之后应该有一个额外的CRLF,最后一个MIME标头之后也应有一个CRLF。

POST /index.php HTTP/1.1
Host: The IP address of my remote server
Connection: Close
User-Agent: My client
Content-Type: multipart/mixed; boundary=be0850c82dd4983ddc49a51a797dce49
--be0850c82dd4983ddc49a51a797dce49
Content-Type: text/plain
value
--be0850c82dd4983ddc49a51a797dce49--

这将修复";坏请求";问题

尽管问题的原因不是Content-Type: multipart/mixed标头,但您应该知道它已被弃用。请改用Content-Type: multipart/form-data。请参阅此处的相关答案和RFC7578。

正确请求示例

内容类型multipart/form-data可用于发送值和文件。区别仅在于属性filename

尽可能少地修改HTTP请求,下面是一个发送两个字段(一个文件和一个值(的示例:

POST /index.php HTTP/1.1
Host: The IP address of my remote server
Connection: Close
User-Agent: My client
Content-Type: multipart/form-data; boundary=be0850c82dd4983ddc49a51a797dce49
Content-Length: 234
--be0850c82dd4983ddc49a51a797dce49
Content-Disposition: form-data; name="one"; filename="example.txt"
foo
--be0850c82dd4983ddc49a51a797dce49
Content-Disposition: form-data; name="two"
bar
--be0850c82dd4983ddc49a51a797dce49--

对于每个字段,您需要一个Content-Disposition标头来命名字段,并可以选择为其提供文件名。

Content-Type是可选的,尽管如果值出现乱码,您可能需要添加一个。

如果您只需要上传一个文件,请根据需要进行修改。

测试请求

下面是一个我用来测试HTTP请求的整洁的小脚本:

<?php
header('Content-Type: application/json');
echo json_encode([
'method' => $_SERVER['REQUEST_METHOD'],
'uri' => $_SERVER['REQUEST_URI'],
'body' => file_get_contents('php://input'),
'GET' => $_GET,
'POST' => $_POST,
'FILES' => $_FILES,
'headers' => getallheaders(),
], JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);

在接收端使用该脚本时,我将示例请求发送到本地主机服务器,但没有修改,得到的结果是:

HTTP/1.1 200 OK
Date: Tue, 31 Jul 2018 11:33:57 GMT
Server: Apache/2.4.9 (Win32)
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
254
{
"method": "POST",
"uri": "/index.php",
"body": "",
"GET": [],
"POST": {
"two": "bar"
},
"FILES": {
"one": {
"name": "example.txt",
"type": "",
"tmp_name": "C:\wamp\tmp\phpD6B5.tmp",
"error": 0,
"size": 3
}
},
"headers": {
"Host": "The IP address of my remote server",
"Connection": "Close",
"User-Agent": "My client",
"Content-Type": "multipart/form-data; boundary=be0850c82dd4983ddc49a51a797dce49",
"Content-Length": "234"
}
}
0

正如你所看到的,字段";一个";转到CCD_ 8;两个";则进入CCD_ 9。

首先,发送示例请求而不进行修改。继续尝试,直到得到正确的结果。然后根据需要进行修改,确保请求的每一步都遵循HTTP规范。

最新更新