read_body timeout when use fastcgi reverse proxy
1. Caddy version (caddy version
):
v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=
2. How I run Caddy:
a. System environment:
vagrant
ubuntu 20.04
systemd
caddy (installed from repo)
php 8
b. Command:
See below
c. Service/unit/compose file:
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
d. My complete Caddyfile or JSON config:
{
servers {
timeouts {
read_body 10s
}
}
}
:80
root * /var/www
route {
@phpFiles path *.php
reverse_proxy @phpFiles unix//run/php/php8.0-fpm.sock {
transport fastcgi {
split php
}
}
respond "caddy
"
}
3. The problem I’m having:
I tried to figure out how timeouts work in caddy and ran into a problem. Perhaps the reason is just my misunderstanding of how caddy works.
I use a simple config where the server passes the php-fpm request if there is .php in the path, or responds with the “respond” directive. I also have a read_body timeout set to 10s. I’m trying to emulate a long request body transfer with curl by specifying Content-Length more than I’m transferring data.
Everything works fine for the case where caddy just responds with “respond”, but it doesn’t work the way I expect it to in the case of php-fpm. If I try to make a request to a php-fpm route with “Content-Length: 2” and an empty request body, the read_body timeout is triggered, but if I make a request with a one byte body, the timeout is never triggered. At the same time, if I execute requests to the “respond” route, the timeout is triggered in both cases. How can this be explained?
These requests are completed in ~10 seconds:
$ time curl -v -H "Content-Length: 2" http://localhost/
* Trying ::1:80...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Length: 2
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Caddy
< Date: Mon, 15 Feb 2021 03:59:05 GMT
< Content-Length: 6
< Connection: close
<
caddy
* Closing connection 0
real 0m10.013s
user 0m0.006s
sys 0m0.006s
$ time curl -v -d A -H "Content-Length: 2" http://localhost/
* Trying ::1:80...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> POST / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 1 out of 1 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Caddy
< Date: Mon, 15 Feb 2021 04:00:02 GMT
< Content-Length: 6
< Connection: close
<
caddy
* Closing connection 0
real 0m10.017s
user 0m0.007s
sys 0m0.007s
$ time curl -v -H "Content-Length: 2" http://localhost/index.php
* Trying ::1:80...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> GET /index.php HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Length: 2
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=UTF-8
< Server: Caddy
< Date: Mon, 15 Feb 2021 03:58:05 GMT
< Content-Length: 4
< Connection: close
<
php
* Closing connection 0
real 0m10.018s
user 0m0.000s
sys 0m0.013s
But this request is never completed:
$ time curl -v -d A -H "Content-Length: 2" http://localhost/index.php
* Trying ::1:80...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> POST /index.php HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 1 out of 1 bytes
^C
real 1m48.580s
user 0m0.009s
sys 0m0.009s
4. Error messages and/or full log output:
–
5. What I already tried:
I think for me this problem is solved by adding timeouts for fastcgi transport or adding a timeout in php-fpm’s config, but I would like to understand why caddy handles these requests this way.
6. Links to relevant resources:
–