Caddy: Modify status code of reverse proxy response

Created on 9 Dec 2019  路  20Comments  路  Source: caddyserver/caddy

Could it be done by only config?
And are there reverse_proxy response placeholders? Such as headers, status_code, body etc.

feature request

All 20 comments

Hi, welcome to the issue tracker!

I am not entirely sure that I understand your post. Do you have 2 questions here?

  1. How to modify the response status code from an upstream?
  2. Whether there are placeholders for reverse proxy? Can you explain more what you mean?

Arguably, you'd say that those configurations should be the responsibility of the upstreams you are passing the request to, i.e. a proxy would only act as a middle-man in a request transaction.
If you want conditionals for different responses then caddy would not be the right answer for you since I'm sure @mholt is steering away from directives like if

Hmmm no I believe this should be possible with Caddy 2, without imperative syntax -- if it's not possible already, then we should implement it. I just need to know exactly what needs to be implemented. So first, we need some clarification from @hackwaly.

I need to use config to achieve:

  • Rewrite headers and status_code of reverse_proxy response (based on reverse_proxy response headers and status_code)

I almost understand -- can you give an actual example of one such configuration you're trying to accomplish?

BTW: I already wrote a go program to get what i want.

Config may like this:

{
  "apps": {
    "proxy_app": {
      "servers": {
        "proxy_server": {
          "routes": [
            {
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "upstreams": [
                    {
                      "dial": "{http.request.header.X-Host}"
                    }
                  ],
                  "headers": {
                    "handler": "headers",
                    "response": {
                      "delete": ["Set-Cookie"],
                      "set": {
                        "X-Set-Cookie": ["{http.handlers.reverse_proxy.response.header.Set-Cookie}"],
                        "Access-Control-Allow-Origin": ["*"]
                      },
                      "set_status_code": "{http.handlers.reverse_proxy.response.status_code >= 400 ? 500 : 200}"
                    }
                  }
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    }
  }
}

@hackwaly Neat, is the source anywhere?

(Reopening until we implement it here)

Ping @hackwaly -- how did you implement that feature?

@mholt
clarify: I haven't implement that for caddy. I implement my need in plain go program -- not use caddy.

Chiming in here since I want to feature that is in the title even though the issue kind of derailed:

My use case is the following. I have a MinIO backend where I serve a static website from. In case it responds with 404 I have an error handler that rewrites the request to /404.html and reverse proxies again to the same minio backend. Tada 馃帀 404-page gets rendered.

The problem is that this will result in a 200 status code for the 404 page which is arguably not ideal. So overwrite the status code would be great.

@fahrradflucht So, in your use case, you don't actually want to _overwrite_ the status code, but you just want Caddy's error handler routes to be invoked on whatever error status is returned from the backend, right? Kind of like nginx's intercept_errors directive?

Maybe I don't fully understand you, but I think I actually want to overwrite the status code. Let me make an example.

Given a Caddyfile like this:

example.com {
    handle_errors {
        @404 {
            expression {http.error.status_code} == 404
        }

        rewrite @404 /404.html
    }

    reverse_proxy https://minio.example.com {
        header_up Host {http.reverse_proxy.upstream.hostport}
        }
}

The 404.html page will be returned for https://example.com/unknown. The problem is that it will be returned with a 200 status code which is not what you usually want. This is why I thought "Well, I need something to tell the reverse_proxy directive to overwrite the status code if the path is /404.html".

Does that make sense? Or am I approaching this totally wrong?

For the sake of correctness, I'm pretty sure the CEL expression should be the following:

expression {http.error.status_code} == 404

Status codes are ints

For the sake of correctness, I'm pretty sure the CEL expression should be the following:

expression {http.error.status_code} == 404

Status codes are ints

Corrected, sorry. I typed this from memory because I don't have the file where I actually had a config like this at hand.

@fahrradflucht Is the backend originating the 404 error? I.e. does minio.example.com return a 404 to Caddy for a request to /unknown?

@fahrradflucht Is the backend originating the 404 error? I.e. does minio.example.com return a 404 to Caddy for a request to /unknown?

Yes, exactly.

@fahrradflucht Okay, then you don't actually want to "overwrite" the status code, you want Caddy to handle the response from the backend as an error, rather than passing it through to the client.

@fahrradflucht Sorry for hijacking this issue but I am trying to use the exact same setup (Caddy reverse proxying to MinIO) and have everything working __but__ custom 404 pages.

I tried using the snippet you provided here:

    handle_errors {
        @404 {
            expression {http.error.status_code} == 404
        }

        rewrite @404 /404.html
    }

but it's not having any effect. Did you ever get that setup working?

For the record, this is my complete config:

example.com {
  handle_errors {
    @404 {
      expression {http.error.status_code} == 404
    }

    rewrite @404 /404.html
  }

  reverse_proxy minio:9000

  @document {
    expression {uri}.endsWith("/")
  }

  @noslash {
    not expression {uri}.endsWith("/")
    path_regexp ^[a-z\-/]*$
  }

  handle @noslash {
    redir {uri}/
  }

  handle {
    route @document {
      rewrite {uri}index.html
    }

    rewrite * /static{uri}
  }

  log
}

@m90 it's not currently possible from the Caddyfile (but it is via JSON). Follow the progress on https://github.com/caddyserver/caddy/pull/3712, where Caddyfile support is being worked on.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

muhammadmuzzammil1998 picture muhammadmuzzammil1998  路  3Comments

PhilmacFLy picture PhilmacFLy  路  3Comments

lorddaedra picture lorddaedra  路  3Comments

la0wei picture la0wei  路  3Comments

jgsqware picture jgsqware  路  3Comments