Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/hillu/go-fcgi-breakage
https://github.com/hillu/go-fcgi-breakage
Last synced: about 2 hours ago
JSON representation
- Host: GitHub
- URL: https://github.com/hillu/go-fcgi-breakage
- Owner: hillu
- Created: 2020-11-25T20:29:57.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2020-11-26T00:25:09.000Z (almost 4 years ago)
- Last Synced: 2024-05-02T02:16:38.119Z (7 months ago)
- Language: Go
- Size: 8.79 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# NGINX + Go `net/http/fcgi` breakage
This is a description of an error condition I ran into when trying to
hook a Go `net/http/fcgi`-based FastCGI application server into nginx,
together with a workaround and a solution:(Found with Go 1.14-2~bpo10+1, nginx 1.14.2-2+deb10u3 on Debian
buster + buster-backports.)## Demonstrating the problem
- Start nginx test instance that passes every HTTP request on
`localhost:8080` to a FastCGI server on `localhost:8081`:
```
$ sudo /usr/sbin/nginx -p . -c ./nginx.conf
```
- Perform a HTTP request containing a body. Since the FastCGI server
has not been started yet, a `502 Bad Gateway` error will be returned
immediately:
```
$ nc localhost 8080 << EOF
> GET /foo HTTP/1.1
> Host: localhost
> Content-Length: 4
>
> abcd
> EOF
HTTP/1.1 502 Bad Gateway
Server: nginx/1.14.2
Date: Wed, 25 Nov 2020 22:00:25 GMT
Content-Type: text/html
Content-Length: 173
Connection: keep-alive
502 Bad Gateway
502 Bad Gateway
nginx/1.14.2
```
- Start the minimal FastCGI application:
```
$ go run fcgi-server.go
```
- Repeat the HTTP request from above. A 10s delay (equal to
`fastcgi_read_timeout`) can be observed before the expected `404 Not
Found` error is returned, even though the trivial "application code" has
taken no delay to process the request:
```
GET /foo HTTP/1.1
Host: localhost
Content-Length: 4
abcd
EOF
HTTP/1.1 404 Not Found
Server: nginx/1.14.2
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Wed, 25 Nov 2020 22:00:57 GMT
X-Content-Type-Options: nosniff```
- An error message indicating the timeout has been written to `error.log`:
```
2020/11/25 23:01:07 [error] 27123#27123: *9 upstream timed out (110: Connection timed out) while reading upstream, client: 127.0.0.1, server: localhost, request: "GET /foo HTTP/1.1", upstream: "fastcgi://127.0.0.1:8081", host: "localhost"
```## Apparent easy workarounds
Setting either `fastcgi_keep_conn on;` or `fastcgi_buffering off;`
appears to make the problem go away.## Analysis
The [FastCGI 1.0 Specification](https://www.mit.edu/~yandros/doc/specs/fcgi-spec.html)
states the following about the `FCGI_KEEP_CONN` flag:> flags & FCGI_KEEP_CONN: If zero, the application closes the
> connection after responding to this request. If not zero, the
> application does not close the connection after responding to this
> request; the Web server retains responsibility for the connection.Using Wireshark, we do not observe the`net/http/fcgi` server closing
the connection. This is curious, because `child.serveRequest` is
supposed to close the connection once it the `http.Handler` has
finished – and we had witnessed that our handler had returned
immediately.Tracing reveals that two `FCGI_STDIN` messages have been transmitted,
but only one is properly processed by `child.handleRecord`. The
second, empty `FCGI_STDIN` message which indicates the end of the
stream is not recognized because the request id has been removed in
`child.serveRequest`, runningin a separate goroutine. Since
`child.handleRecord` cannot detect the end of the "standard input"
stream, it will not close the pipe transporting request body data to
`child.serveRequest`, stalling it while it is trying to consume the
request body.## Fix
Moving the lines of code that remove the request id from
`serveRequest` to `handleRecord` eliminates the race condition. The
`fcgi/` subdirectory contains a fixed version of `net/fcgi` from Go
1.14.2. Changing the corresponding import in `fcgi-server.go` can be
used to demonstrate the fix.## Author
Hilko Bengen <>