我们有一个在 gunicorn 中运行的 Python Flask API,由 apache 提供前端。
ProxyPreserveHost On
<Location /api/v2>
ProxyPass http://127.0.0.1:8090/ disablereuse=on
SetEnv proxy-sendcl
</Location>
如果上传的文件超过一定大小,python API 会引发错误413
。直接访问 python API 时,响应会正确返回,但是当将 apache 添加到组合中时,会502
返回错误,而 apache 错误日志中没有任何错误。
user@server:~$ curl -v -X POST http://localhost:8090/photos -F [email protected]
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8090 (#0)
> POST /photos HTTP/1.1
> Host: localhost:8090
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Length: 31457564
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------5333e9e102a557ee
>
< HTTP/1.1 100 Continue
< HTTP/1.1 413 REQUEST ENTITY TOO LARGE
< Server: gunicorn/19.6.0
< Date: Fri, 21 Sep 2018 18:38:09 GMT
< Connection: close
< Content-Type: application/json
< Content-Length: 76
<
{
"message": "The data value transmitted exceeds the capacity limit."
}
* we are done reading and this is set to close, stop send
* Closing connection 0
502
当 apache 作为代理时,会发生以下情况:
$ curl -v -X POST \
https://my.servers.com/photos \
-F [email protected]
* Trying xx.xx.xx.xxx...
* TCP_NODELAY set
* Connected to my.server.com (xx.xx.xx.xxx) port 443 (#0)
... SSL ...
> POST /api/v2/photos HTTP/1.1
> Host: my.servers.com
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 42716348
> Expect: 100-continue
> Content-Type: application/x-www-form-urlencoded; boundary=------------------------5bc19156b7a56f0e
>
* Done waiting for 100-continue
< HTTP/1.1 502 Bad Gateway
< Date: Fri, 21 Sep 2018 20:21:13 GMT
< Server: Apache
< Content-Length: 232
< Content-Type: text/html; charset=iso-8859-1
* HTTP error before end of send, stop sending
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>502 Bad Gateway</title>
</head><body>
<h1>Bad Gateway</h1>
<p>The proxy server received an invalid
response from an upstream server.<br />
</p>
</body></html>
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, Client hello (1):
我尝试过的:
- 在 Apache 本身中设置限制,但该限制不适用于代理
- https://stackoverflow.com/questions/3889574/apache-and-mod-proxy-not-handling-http-100-continue-from-client-http-417
proxy-sendcl
在代理设置中设置代理环境变量。像这儿
知道为什么 Apache 不传递它吗413
?
答案1
我将按出现的顺序列出我看到的问题。
您的服务器(运行 PHP)正在等待“Content-Type:multipart/form-data”。它似乎发送了“Content-Type:application/json”。
您的代理正在向期望“Content-Type:multipart/form-data”的服务器发送内容类型“Content-Type:application/x-www-form-urlencoded”。
我的第一个问题是,如果通过 Apache 代理发送正确(可接受)大小的文件,服务器(运行 PHP)是否能正确处理该文件?
如果没有发生这种情况,Apache 代理将会看到“发送结束前出现 HTTP 错误,停止发送”,因为服务器(运行 PHP 的服务器)不会识别内容类型并抛出错误(基于内容类型的无效响应)并向客户端显示 502,而不是传递 413。
代理中的这行配置(您需要将 FQDN 配置到您的目的地并优化变量)是否解决了您的问题(在确定目标服务器正确处理正确大小/格式的图形之后)?
ProxyPass / http://localhost:8090/ retry=1 acquire=3000 timeout=600 Keepalive=On