-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
Hello, I was attempting to support Transfer-Encoding: chunked header into my application, and noticed that the server never responses if the header is used.
$ caddy version
v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=Caddyfile
{
debug
log stdout
admin 0.0.0.0:2018
grace_period 1s
}
:8888 {
log
root * /home/user/test
php_fastcgi unix//var/run/php/php8.1-fpm.sock {
#buffer_requests
#flush_interval -1
}
}
php file (index.php)
<?php
echo "i am alive\n";Example of working request/response
$ curl -k http://localhost:8888/ --header "Pragma: no-cache" -X POST -d file=test
i am alive
Caddy Logs
2022/12/06 14:41:18.348 DEBUG http.handlers.rewrite rewrote request {"request": {"remote_ip": "127.0.0.1", "remote_port": "49996", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/", "headers": {"Content-Length": ["9"], "Content-Type": ["application/x-www-form-urlencoded"], "Cache-Control": ["no-cache"], "User-Agent": ["curl/7.81.0"], "Accept": ["*/*"], "Pragma": ["no-cache"]}}, "method": "POST", "uri": "/index.php"}
2022/12/06 14:41:18.348 DEBUG http.handlers.reverse_proxy selected upstream {"dial": "/var/run/php/php8.1-fpm.sock", "total_upstreams": 1}
2022/12/06 14:41:18.348 DEBUG http.reverse_proxy.transport.fastcgi roundtrip {"request": {"remote_ip": "127.0.0.1", "remote_port": "49996", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/index.php", "headers": {"User-Agent": ["curl/7.81.0"], "Pragma": ["no-cache"], "X-Forwarded-For": ["127.0.0.1"], "X-Forwarded-Proto": ["http"], "X-Forwarded-Host": ["localhost:8888"], "Cache-Control": ["no-cache"], "Accept": ["*/*"], "Content-Length": ["9"], "Content-Type": ["application/x-www-form-urlencoded"]}}, "env": {"GATEWAY_INTERFACE": "CGI/1.1", "REMOTE_IDENT": "", "CONTENT_LENGTH": "9", "SERVER_PORT": "8888", "HTTP_CONTENT_LENGTH": "9", "REMOTE_HOST": "127.0.0.1", "REMOTE_PORT": "49996", "HTTP_HOST": "localhost:8888", "HTTP_CACHE_CONTROL": "no-cache", "HTTP_PRAGMA": "no-cache", "REQUEST_METHOD": "POST", "DOCUMENT_ROOT": "/home/user/test", "REQUEST_URI": "/", "REMOTE_ADDR": "127.0.0.1", "REMOTE_USER": "", "HTTP_CONTENT_TYPE": "application/x-www-form-urlencoded", "PATH_INFO": "", "SERVER_PROTOCOL": "HTTP/1.1", "HTTP_ACCEPT": "*/*", "CONTENT_TYPE": "application/x-www-form-urlencoded", "AUTH_TYPE": "", "REQUEST_SCHEME": "http", "SERVER_NAME": "localhost", "SCRIPT_FILENAME": "/home/user/testindex.php", "HTTP_X_FORWARDED_PROTO": "http", "HTTP_X_FORWARDED_HOST": "localhost:8888", "HTTP_USER_AGENT": "curl/7.81.0", "QUERY_STRING": "", "SERVER_SOFTWARE": "Caddy/v2.6.2", "DOCUMENT_URI": "/index.php", "SCRIPT_NAME": "/index.php", "HTTP_X_FORWARDED_FOR": "127.0.0.1"}, "dial": "/var/run/php/php8.1-fpm.sock", "env": {"REQUEST_METHOD": "POST", "DOCUMENT_ROOT": "/home/user/test", "REQUEST_URI": "/", "REMOTE_ADDR": "127.0.0.1", "REMOTE_USER": "", "HTTP_CONTENT_TYPE": "application/x-www-form-urlencoded", "PATH_INFO": "", "SERVER_PROTOCOL": "HTTP/1.1", "HTTP_ACCEPT": "*/*", "CONTENT_TYPE": "application/x-www-form-urlencoded", "SCRIPT_FILENAME": "/home/user/testindex.php", "HTTP_X_FORWARDED_PROTO": "http", "HTTP_X_FORWARDED_HOST": "localhost:8888", "HTTP_USER_AGENT": "curl/7.81.0", "AUTH_TYPE": "", "REQUEST_SCHEME": "http", "SERVER_NAME": "localhost", "SCRIPT_NAME": "/index.php", "HTTP_X_FORWARDED_FOR": "127.0.0.1", "QUERY_STRING": "", "SERVER_SOFTWARE": "Caddy/v2.6.2", "DOCUMENT_URI": "/index.php", "SERVER_PORT": "8888", "HTTP_CONTENT_LENGTH": "9", "GATEWAY_INTERFACE": "CGI/1.1", "REMOTE_IDENT": "", "CONTENT_LENGTH": "9", "HTTP_CACHE_CONTROL": "no-cache", "HTTP_PRAGMA": "no-cache", "REMOTE_HOST": "127.0.0.1", "REMOTE_PORT": "49996", "HTTP_HOST": "localhost:8888"}, "request": {"remote_ip": "127.0.0.1", "remote_port": "49996", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/index.php", "headers": {"Cache-Control": ["no-cache"], "Accept": ["*/*"], "Content-Length": ["9"], "Content-Type": ["application/x-www-form-urlencoded"], "User-Agent": ["curl/7.81.0"], "Pragma": ["no-cache"], "X-Forwarded-For": ["127.0.0.1"], "X-Forwarded-Proto": ["http"], "X-Forwarded-Host": ["localhost:8888"]}}}
2022/12/06 14:41:18.349 DEBUG http.handlers.reverse_proxy upstream roundtrip {"upstream": "unix//var/run/php/php8.1-fpm.sock", "duration": 0.000485466, "request": {"remote_ip": "127.0.0.1", "remote_port": "49996", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/index.php", "headers": {"Accept": ["*/*"], "Content-Length": ["9"], "Content-Type": ["application/x-www-form-urlencoded"], "Cache-Control": ["no-cache"], "Pragma": ["no-cache"], "X-Forwarded-For": ["127.0.0.1"], "X-Forwarded-Proto": ["http"], "X-Forwarded-Host": ["localhost:8888"], "User-Agent": ["curl/7.81.0"]}}, "headers": {"Content-Type": ["text/html; charset=UTF-8"]}, "status": 200}
2022/12/06 14:41:18.349 INFO http.log.access handled request {"request": {"remote_ip": "127.0.0.1", "remote_port": "49996", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/", "headers": {"Cache-Control": ["no-cache"], "User-Agent": ["curl/7.81.0"], "Accept": ["*/*"], "Pragma": ["no-cache"], "Content-Length": ["9"], "Content-Type": ["application/x-www-form-urlencoded"]}}, "user_id": "", "duration": 0.000779217, "size": 1788, "status": 200, "resp_headers": {"Server": ["Caddy"], "Content-Type": ["text/html; charset=UTF-8"]}}
Example of not working request/response
$ curl -k http://localhost:8888/ --header "Pragma: no-cache" -X POST -d file=test --header "Transfer-Encoding: chunked" -vvv
hangs forever. no response.
Caddy logs.
2022/12/06 14:46:23.786 DEBUG http.handlers.rewrite rewrote request {"request": {"remote_ip": "127.0.0.1", "remote_port": "43034", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/", "headers": {"Accept": ["*/*"], "User-Agent": ["curl/7.81.0"], "Pragma": ["no-cache"], "Content-Type": ["application/x-www-form-urlencoded"], "Cache-Control": ["no-cache"]}}, "method": "POST", "uri": "/index.php"}
2022/12/06 14:46:23.786 DEBUG http.handlers.reverse_proxy selected upstream {"dial": "/var/run/php/php8.1-fpm.sock", "total_upstreams": 1}
2022/12/06 14:46:23.786 DEBUG http.reverse_proxy.transport.fastcgi roundtrip {"request": {"remote_ip": "127.0.0.1", "remote_port": "43034", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/index.php", "headers": {"Pragma": ["no-cache"], "Content-Type": ["application/x-www-form-urlencoded"], "Cache-Control": ["no-cache"], "User-Agent": ["curl/7.81.0"], "X-Forwarded-For": ["127.0.0.1"], "X-Forwarded-Proto": ["http"], "X-Forwarded-Host": ["localhost:8888"], "Accept": ["*/*"]}}, "env": {"SCRIPT_FILENAME": "/home/user/test/index.php", "HTTP_CONTENT_TYPE": "application/x-www-form-urlencoded", "HTTP_USER_AGENT": "curl/7.81.0", "HTTP_X_FORWARDED_PROTO": "http", "AUTH_TYPE": "", "REMOTE_IDENT": "", "REMOTE_USER": "", "REQUEST_SCHEME": "http", "DOCUMENT_ROOT": "/home/user/test", "SERVER_NAME": "localhost", "HTTP_X_FORWARDED_FOR": "127.0.0.1", "REMOTE_ADDR": "127.0.0.1", "HTTP_X_FORWARDED_HOST": "localhost:8888", "PATH_INFO": "", "QUERY_STRING": "", "SERVER_SOFTWARE": "Caddy/v2.6.2", "GATEWAY_INTERFACE": "CGI/1.1", "SERVER_PROTOCOL": "HTTP/1.1", "REQUEST_URI": "/", "HTTP_ACCEPT": "*/*", "HTTP_PRAGMA": "no-cache", "HTTP_CACHE_CONTROL": "no-cache", "CONTENT_LENGTH": "", "REMOTE_HOST": "127.0.0.1", "DOCUMENT_URI": "/index.php", "CONTENT_TYPE": "application/x-www-form-urlencoded", "REMOTE_PORT": "43034", "REQUEST_METHOD": "POST", "HTTP_HOST": "localhost:8888", "SCRIPT_NAME": "/index.php", "SERVER_PORT": "8888"}, "dial": "/var/run/php/php8.1-fpm.sock", "env": {"REMOTE_ADDR": "127.0.0.1", "HTTP_X_FORWARDED_HOST": "localhost:8888", "PATH_INFO": "", "QUERY_STRING": "", "SERVER_SOFTWARE": "Caddy/v2.6.2", "HTTP_ACCEPT": "*/*", "HTTP_PRAGMA": "no-cache", "HTTP_CACHE_CONTROL": "no-cache", "GATEWAY_INTERFACE": "CGI/1.1", "SERVER_PROTOCOL": "HTTP/1.1", "REQUEST_URI": "/", "CONTENT_LENGTH": "", "REMOTE_HOST": "127.0.0.1", "DOCUMENT_URI": "/index.php", "HTTP_HOST": "localhost:8888", "SCRIPT_NAME": "/index.php", "SERVER_PORT": "8888", "CONTENT_TYPE": "application/x-www-form-urlencoded", "REMOTE_PORT": "43034", "REQUEST_METHOD": "POST", "HTTP_X_FORWARDED_PROTO": "http", "SCRIPT_FILENAME": "/home/user/test/index.php", "HTTP_CONTENT_TYPE": "application/x-www-form-urlencoded", "HTTP_USER_AGENT": "curl/7.81.0", "REQUEST_SCHEME": "http", "DOCUMENT_ROOT": "/home/user/test", "AUTH_TYPE": "", "REMOTE_IDENT": "", "REMOTE_USER": "", "SERVER_NAME": "localhost", "HTTP_X_FORWARDED_FOR": "127.0.0.1"}, "request": {"remote_ip": "127.0.0.1", "remote_port": "43034", "proto": "HTTP/1.1", "method": "POST", "host": "localhost:8888", "uri": "/index.php", "headers": {"Content-Type": ["application/x-www-form-urlencoded"], "Cache-Control": ["no-cache"], "User-Agent": ["curl/7.81.0"], "X-Forwarded-For": ["127.0.0.1"], "X-Forwarded-Proto": ["http"], "X-Forwarded-Host": ["localhost:8888"], "Accept": ["*/*"], "Pragma": ["no-cache"]}}}
i also tried with buffer_requests and flush_interval -1 and it seems to have no effect.
This behavior led me to believe it was an issue with PHP itself, however digging deeper i was able to find this issue php bug #60826, reading the replies this suggest the problem is not conforming to fastcgi spec
Essentially, PHP is following the spec, and not reading beyond the FastCGI CONTENT_LENGTH header value - so correct fixes are necessarily above PHP, in the FastCGI or web server implementation.
In a strict sense this is indeed not a PHP bug, because the CGI specification (which is only informational, though), mandates[1]:
As transfer-codings are not supported on the request-body, the server MUST remove any such codings from the message-body, and recalculate the CONTENT_LENGTH. If this is not possible (for example, because of large buffering requirements), the server SHOULD reject the client request.
It seems apache also had the bug and they have somewhat working fix at https://bz.apache.org/bugzilla/show_bug.cgi?id=57087
I tried to see if the request itself is valid i used python gunicorn to test
curl http://httpbin/post --header "Pragma: no-cache" -d file=test --header "Transfer-Encoding: chunked" -vvv
* Trying 172.17.0.2:80...
* Connected to httpbin (172.17.0.2) port 80 (#0)
> POST /post HTTP/1.1
> Host: httpbin
> User-Agent: curl/7.81.0
> Accept: */*
> Pragma: no-cache
> Transfer-Encoding: chunked
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: gunicorn/19.9.0
< Date: Tue, 06 Dec 2022 15:01:59 GMT
< Connection: keep-alive
< Content-Type: application/json
< Content-Length: 383
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
<
{
"args": {},
"data": "",
"files": {},
"form": {
"file": "test"
},
"headers": {
"Accept": "*/*",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin",
"Pragma": "no-cache",
"Transfer-Encoding": "chunked",
"User-Agent": "curl/7.81.0"
},
"json": null,
"origin": "172.17.0.1",
"url": "http://httpbin/post"
}
* Connection #0 to host httpbin left intact