Rewrite and header directives

Couple of issues which I can’t seem to resolve:

  1. This rewrite directive doesn’t seem to work for me to “strip” off foo from requests where foo is present:
rewrite /foo {
	r  ^/foo/\w+(/.*)
	to {1}       
}

changing the rewrite to this instead does work but doesn’t make sense:

rewrite / {
	r  ^/foo/\w+(/.*)
	to {1}       
}
  1. Having the rewrite above in the caddyfile, and attempting to add a header to every request which did start with /foo doesn’t seem to add the header
header /foo {
   expires "Sun, 09 Sep 2026 05:00:00 GMT"
}

No expires header appears in the response

caddyfile:

bar.com {

   header /foo {
     expires "Sun, 09 Sep 2026 05:00:00 GMT"
   }

   rewrite /foo {
	r  ^/foo/\w+(/.*)
	to {1}       
   }

log / stdout "{proto} Request: {method} {path} {rewrite_path}"
}

Hi @Richard_Stupek,

I’ve edited your post to format the Caddyfile content in code blocks for readability.

Do you have Caddy log lines from when this rewrite fails to operate as expected?

I believe this is expected behaviour as rewrite operates before header does - you’ll need to add the header to the URI you’re rewriting to, not the one you’re rewriting from.

1 Like

The log line shows the following when using rewrite /foo (or rewrite /foo/)
HTTP/2.0 Request: GET 0t.b5z.net/foo/111/i/u/424807/i/choppers_apparel.jpg /foo/111/i/u/424807/i/choppers_apparel.jpg 404
when using rewrite / it is:
HTTP/2.0 Request: GET 0t.b5z.net/zirw/111/i/u/424807/i/choppers_apparel.jpg /i/u/424807/i/choppers_apparel.jpg 200

On the header, I need to have the header added only when /foo is present in the url. Is there a way I can do that?

Also something else I noticed but haven’t setup a test scenario for is that within the proxy directive with an except setting it wouldn’t proxy requests I thought it should be proxying. the following excerpt from caddyfile

proxy / http://10.1.3.72 {
transparent
except /i/
}

requests to /inc were not being proxied and a 404 error was returned

Consider using a path scoped site label. You shouldn’t even need a rewrite in this case. I also used the opportunity to test your proxy except issue, and demonstrate applying the header for requests starting /foo. The example Caddyfile:

:2015 {
  proxy / localhost:2016 {
    except /i/
  }
  log / stdout "{proto} Request: {path} {upstream}"
}

:2015/foo {
  root /users/whitestrake/projects/test/files
  header / {
    expires "Sun, 09 Sep 2026 05:00:00 GMT"
  }
  log / stdout "{proto} Request: {method} {path} {rewrite_path}"
}

:2016 {
  status 200 /
}

The tests:

whitestrake at apollo in ~/Projects/test
❯ curl -IL localhost:2015/foo/111/index.txt
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=utf-8
Expires: Sun, 09 Sep 2026 05:00:00 GMT
Location: /foo/111/
Server: Caddy
Date: Thu, 05 Apr 2018 23:48:38 GMT

HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 14
Content-Type: text/plain; charset=utf-8
Etag: "p6qkoae"
Expires: Sun, 09 Sep 2026 05:00:00 GMT
Last-Modified: Thu, 05 Apr 2018 23:45:46 GMT
Server: Caddy
Date: Thu, 05 Apr 2018 23:48:38 GMT

whitestrake at apollo in ~/Projects/test
❯ curl -IL localhost:2015/inc
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
Server: Caddy
X-Content-Type-Options: nosniff
Date: Thu, 05 Apr 2018 23:48:39 GMT
Content-Length: 14

whitestrake at apollo in ~/Projects/test
❯ curl -IL localhost:2015
HTTP/1.1 200 OK
Date: Thu, 05 Apr 2018 23:48:41 GMT
Server: Caddy
Server: Caddy

The log output:

HTTP/1.1 Request: HEAD /foo/111/index.txt /111/index.txt
HTTP/1.1 Request: HEAD /foo/111/ /111/
HTTP/1.1 Request: /inc -
HTTP/1.1 Request: / http://localhost:2016

The issue with the proxy is that the exception /i/ is saved, but during the comparison, the result of a path.Clean is what’s actually checked against, which removes the trailing slash; effectively, except /i/ is the same as except /i.

https://github.com/mholt/caddy/blob/88edca65d3b1b7fb533f5abe7c1a95a417a5d016/caddyhttp/proxy/upstream.go#L603-L610

thanks I’ll definitely try that. the except issue, is that a bug since it seems counter intuitive and I think it happens with a lot of the config settings?

I agree. It gets a bit complicated, I think, because the path.Clean is very useful in ensuring the result of the path.Join is valid. Perhaps some extra checking could be done for a trailing slash, to be re-added to the result if necessary prior to the comparison.

Would you mind heading to https://github.com/mholt/caddy/issues, filling out a new template for the proxy except issue, and linking to this thread?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.