Bug #11376

FastCGI with progressive bootstrap fails to redirect with some web servers

Added by Roel Standaert 30 days ago. Updated 16 days ago.

Target version:
Start date:
Due date:
% Done:


Estimated time:


This is something I noticed when using Caddy as a reverse proxy:

I placed the following Caddyfile in the examples/widgetgallery directory, and then I run Caddy with caddy run from that directory:


encode zstd gzip
root docroot

@widgetgallery {
    path /widgetgallery.wt
    path /widgetgallery.wt/*

reverse_proxy @widgetgallery unix/widgetgallery.sock {
    transport fastcgi {
        split /widgetgallery.wt

handle_path /resources/* {
    file_server {
        root ../../resources

I compiled widgetgallery.wt with -DEXAMPLES_CONNECTOR=wtfcgi, and use spawn-fcgi (from the examples/widgetgallery directory):

WT_APP_ROOT=$(pwd)/approot spawn-fcgi -s $(pwd)/widgetgallery.sock -n -- /path/to/widgetgallery.wt

If I then request http://localhost:8080/widgetgallery.wt the response is:

$ curl -v http://localhost:8080/widgetgallery.wt
*   Trying
* Connected to localhost ( port 8080 (#0)
> GET /widgetgallery.wt HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Location: widgetgallery.wt/layout/
< Server: Caddy
< Date: Fri, 24 Feb 2023 09:27:35 GMT
< Content-Length: 55
< Content-Type: text/plain; charset=utf-8
Content-Type: text/html; charset=UTF-8
Status: 302

* Connection #0 to host localhost left intact

Instead of getting the 302 status code, I'm getting a 200 status code with a response body containing the "Status: 302" string.

The culprit is the extra \r\n here (in src/fcgi/FCGIStream.C):

virtual void setRedirect(const std::string& url) override
  *out_ << "Location: " << url << "\r\n\r\n";

The double \r\n\r\n indicates to the web server that all headers were sent. This went unnoticed since other web servers, like Apache, appear to tolerate this as long as the Status: line is not sent.


Updated by Roel Standaert 30 days ago

  • Assignee deleted (Roel Standaert)

Updated by Roel Standaert 30 days ago

  • Status changed from InProgress to Review

Updated by Roel Standaert 16 days ago

  • Status changed from Review to Resolved
  • Assignee set to Roel Standaert
  • % Done changed from 0 to 100

Also available in: Atom PDF