HTTP Error Header missing text

1. Caddy version (caddy version):

v2.4.6 h1:HGkGICFGvyrodcqOOclHKfvJC0qTU7vny/7FhYp9hNw=

2. How I run Caddy:

via local executable, eg:

./caddy run --config caddy_config.json

I’m using Caddy to expose my local environment to the internet (required for oAuth service redirects and webhooks).

a. System environment:

Ubuntu 18.04 vagrant

b. Command:

./caddy run --config caddy_config.json

d. My complete Caddyfile or JSON config:

{"apps":{"http":{"servers":{"tunnelsh":{"listen":[":443",":80"],"routes":[{"@id":"procfu.lcldev.globi.ca-9001","handle":[{"handler":"reverse_proxy","upstreams":[{"dial":":9001"}]}],"match":[{"host":["procfu.lcldev.globi.ca"]}]}]}}}}}

3. The problem I’m having:

Caddy is not returning HTTP status messages.

With this PHP script:

header("HTTP/1.1 500 foo bar baz");
exit();

I expect and get, when accessing directly:

$ curl -v procfu.vg18/tinker/headers.php
*   Trying 192.168.33.22:80...
* TCP_NODELAY set
* Connected to procfu.vg18 (192.168.33.22) port 80 (#0)
> GET /tinker/headers.php HTTP/1.1
> Host: procfu.vg18
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 foo bar baz
< Date: Thu, 02 Dec 2021 14:11:51 GMT
< Server: Apache/2.4.29 (Ubuntu)
< Set-Cookie: PHPSESSID=2lc4dba04goh7337no10u3cnf5; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate
< Pragma: no-cache
< Content-Length: 0
< Connection: close
< Content-Type: text/html; charset=UTF-8
< 
* Closing connection 0

But through Caddy Reverse Proxy, the error text is stripped out:

$ curl -v procfu.lcldev.globi.ca/tinker/headers.php
*   Trying 128.199.1.162:80...
* TCP_NODELAY set
* Connected to procfu.lcldev.globi.ca (128.199.1.162) port 80 (#0)
> GET /tinker/headers.php HTTP/1.1
> Host: procfu.lcldev.globi.ca
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< Cache-Control: no-store, no-cache, must-revalidate
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 02 Dec 2021 14:11:35 GMT
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Pragma: no-cache
< Server: Caddy
< Server: Apache/2.4.29 (Ubuntu)
< Set-Cookie: PHPSESSID=qi6ipj0hsnkinsmj6hdrpicipl; path=/
< 
* Connection #0 to host procfu.lcldev.globi.ca left intact

In Chrome/Firefox there is no status message text at all.

This makes it impossible for client-side JavaScript to properly deal with errors.

How can I get the message text to pass through with the status code?

Note: everything works fine without Caddy. Production servers through a load balancer return the correct status message, public dev servers return the correct status message, and my local vagrant returns the correct status message when accessed directly.

It’s only when accessing via Caddy’s reverse proxy that the status message is stripped out.

1 Like

It’s probably an oversight in our proxy implementation. You can open an issue on GitHub, and we’ll take a closer look at resolving it.

1 Like

I took a look, and actually, your usecase isn’t supported in HTTP/2 and later. Reason phrases are no longer in the spec:

https://www.rfc-editor.org/rfc/rfc7540#section-8.1.2.4

I suggest you find a different way to send your error message back to the client. Either with a response header, or in the response body.

1 Like

But I’m sending HTTP/1.1 headers

Caddy is a modern HTTP server with support for HTTP/2 (and experimental support for HTTP/3). I think it’s not a good idea to support deprecated parts of HTTP.

I understand your position.

But there are TONS of websites out there which are sending even HTTP/1.0 headers.

If there’s logic that depends on the reason phrase, then it wasn’t doing HTTP correctly. It’s not meant to be used that way. See the HTTP/1.1 spec:

https://www.rfc-editor.org/rfc/rfc7230#section-3.1.2

The reason-phrase element exists for the sole purpose of providing a
textual description associated with the numeric status code, mostly
out of deference to earlier Internet application protocols that were
more frequently used with interactive text clients. A client SHOULD
ignore the reason-phrase content.

Yes - I understand that.

And I can code my own sites to follow the spec more closely.

But I cannot fix the other sites I’m trying to proxy.

The reason I was sending a response message and using it, is because almost EVERY stackoverflow post suggests this as a solution.

All I’m trying to say is that there are tons of other websites that won’t work through caddy. It’s academic to suggest they’re doing things wrong. In reality they just don’t work properly through caddy.

Sorry about the frustration, but I don’t think there’s anything we can do about it. The Go standard library won’t let us customize the status text without re-implementing HTTP ourselves. Status texts are viewed as kind of a misfeature in HTTP, so modern HTTP versions don’t have them.

2 Likes

Thanks for looking into it.

I guess Caddy is not for me. I only ended up here because ngrok started dying for the same reason.

Maybe HAProxy will be a better fit for my needs.

This topic was automatically closed after 30 days. New replies are no longer allowed.