Simpler way for a redirection


I want to redirect a path without an ending slash to slashed version, but I want also to take into account query part. So something like this:
a) /test redir to /test/
b) /test?q=hello redir to /test/?q=hello

A simple

redir /test /test/

only covers (a) case. I can also do

redir /test /test/?{query}

but then (a) case is redirected to /test/? that is not wrong (AFAIK) but is kind of “ugly”.

In the end I did a more complicated approach:

@unslashedquery expression {path} == '/test' && {query} != ''
redir @unslashedquery /test/?{query}
redir /test /test/

So my question is, is there a simpler way of doing this? Am I overcomplicating things?


Howdy @cfinnberg, welcome to the Caddy community.

The implied matcher is a path matcher, not a path+query matcher.

redir /test /test/ will catch a request to /test?query=foo.

If you want to be lazy, you can just redir to /test/?{query}. It’ll add a dangling ? to all unslashed requests, but that’s not exactly a massive issue at all.

➜ caddy version
v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=

➜ cat Caddyfile
http:// {
  redir /test /test/?{query}

➜ curl -I 'localhost/test'
HTTP/1.1 302 Found
Location: /test/?
Server: Caddy
Date: Wed, 05 Jun 2024 07:01:08 GMT

➜ curl -I 'localhost/test?query=account'
HTTP/1.1 302 Found
Location: /test/?query=account
Server: Caddy
Date: Wed, 05 Jun 2024 07:01:09 GMT

Thanks for the reply!

Yes, I noticed already that, as stated in my original question, but I was looking for a simpler way of doing it just the way I want (that is, no question mark if no query). More precisely I am looking for a simpler way to match the ‘/test?’ part (with the question mark) on the original URI.

If not, I will just stick to what I already have, as it works correctly :slight_smile:

Ahh, you’re right, sorry - I skimmed over the ‘but then (a) case… is kind of “ugly”’ part!

You could probably regexp it to do it in one go, but that’s not very efficient on resources. Your CEL expression is probably the most efficient way to do it.

Thanks again!

Let it be then! :smiley:

1 Like

You can slightly shorten this:

@unslashedquery `{path} == '/test' && {query} != ''`

Using backticks around it lets you omit expression, reads a bit nicer.