【问题标题】:Is this HTTP request valid?这个 HTTP 请求有效吗?
【发布时间】:2024-01-05 08:18:01
【问题描述】:

我用swagger-codegen 制作了一个python 服务器。我有一个端点接收带有mutlipart/form-data的文件

并且还创建了一个带有go-swagger 的客户端进行测试。

创建了要上传的文件:$ echo "123file content321" > data

并使用客户端将文件上传到服务器。生成的 HTTP 请求如下所示:

POST /api/order/1/attachment HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Go-http-client/1.1
Transfer-Encoding: chunked
Accept: application/json
Content-Type: multipart/form-data; boundary=5f3f0ad86e6345b77c869cbe0a5e608f038354cf9ceab74ec2533d7555c0
Accept-Encoding: gzip

ff
--5f3f0ad86e6345b77c869cbe0a5e608f038354cf9ceab74ec2533d7555c0
Content-Disposition: form-data; name="file"; filename="data"
Content-Type: application/octet-stream

123file content321

--5f3f0ad86e6345b77c869cbe0a5e608f038354cf9ceab74ec2533d7555c0--

但服务器不接受并响应:

HTTP/1.0 400 BAD REQUEST
Connection: close
Content-Length: 120
Content-Type: application/problem+json
Date: Fri, 19 May 2017 15:15:44 GMT
Server: Werkzeug/0.12.1 Python/3.6.1
{
  "type": "about:blank",
  "title": "Bad Request",
  "detail": "Missing formdata parameter 'file'",
  "status": 400
}

所以请求没有被正确解析。但是当我使用 swagger-ui 时,文件已正确上传。是客户端的请求有问题,还是服务器有问题?

编辑:我认为缺少 Content-Lenght 或 BODY 开头的 ff 可能不存在

EDIT2:swagger-ui 请求:

POST /api/order/1/attachment HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 211
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypzmNwrDR7zzpZ7SJ
Accept: application/json
X-Requested-With: XMLHttpRequest
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

------WebKitFormBoundarypzmNwrDR7zzpZ7SJ
Content-Disposition: form-data; name="file"; filename="data"
Content-Type: application/octet-stream

123file content321

------WebKitFormBoundarypzmNwrDR7zzpZ7SJ--

【问题讨论】:

  • 客户端和服务器需要在HTTP 1.1和1.0之间进行协商,因为服务器使用的是HTTP 1.0;如果您可以控制服务器,只需将属性 protocol_version = "HTTP/1.1" 添加到您的 BaseHTTPRequestHandler 子类(请参阅github.com/mineralsprings/json-api-host/blob/master/…
  • "detail": "Missing formdata parameter 'file'" 似乎希望它是 file="name" 而不是 name="file"
  • name="file" 我认为是正确的,因为那是表单参数的名称。我错过了 HTTP 版本不匹配。我用python -m swagger_server 运行测试服务器我可以添加一些参数来用HTTP/1.1 运行BaseHTTPServer 吗?或者以某种方式配置烧瓶框架?
  • 好吧,我们需要服务器的来源知道为什么它认为这是一个错误的请求,因为我认为它的格式很好。
  • 你能把swagger-ui正在发送的请求贴出来进行比较吗?打开开发工具并查看请求。这可能会对此有所了解。

标签: python http go httprequest swagger


【解决方案1】:

您发送的第一个请求是使用分块传输编码的 HTTP/1.1 请求。这意味着主体由多个块组成,其中每个块都以十六进制大小为前缀,然后是\r\n,然后是数据,然后是\r\n。我不确定您显示的正文开头的 ff 是否真的指定了以下数据的大小(即 255 字节)。但是,最后一个大小为 0 的块丢失了,所以这个请求是不完整的。但也许你只是省略了这个问题中缺少的部分。

除此之外,服务器正在响应版本 HTTP/1.0。分块传输编码仅针对 HTTP/1.1 定义,这意味着 HTTP/1.0 服务器不会理解此请求。甚至不是所有的 HTTP/1.1 服务器都会理解请求中的分块传输编码,即使它们应该理解。

您显示的第二个请求(由 Chrome 创建)不使用分块传输编码,而是在 HTTP 标头中使用 Content-length 指定标头的长度。这是您应该采用的方式,因为它适用于所有 Web 服务器,包括 HTTP/1.0 服务器。

【讨论】:

  • 最后 0 块在那里,但我不知道 0 是请求的一部分。我现在必须找出如何告诉 go http 客户端不要使用 http 分块传输。谢谢:)
【解决方案2】:

根据您发布的两个请求,我将首先尝试在您的 go 请求上设置 Content-Length 并对其进行测试。我之前遇到过 ArangoDB HTTP API 不接受没有正确内容长度值的请求的问题。

如果成功,那么是的。

否则,您请求中的 ff 是我接下来要删除的内容。但我会先关注Content-Length 标头。

【讨论】: