Redirect with if statements based on value

Hey everyone, love Caddy but I’m new to it.

I have a website supporting german and english languages which will redirect to /en/ or /de/ depending on the language found in the Accept-Language header of the client. I decided to use this plugin to achieve this GitHub - simia-tech/caddy-locale: Locale detection for caddy

It works great for most browsers where either en or de is specified but in some cases i see that IE11 only sends a de-DE value and I was wondering how I can redirect based on this value. Currently I have this code which is not working, I have tried to add if statements to redirect de-DE to /de/ but this does not work as it complains that I have too many / redirects or something.

Can someone help explain to me how I can redirect de-DE to /de/?

localhost:8080 {
    gzip
    log ./access.log
    tls self_signed

    locale en de de-DE {
      detect header
    }

     redir {
        if {path} is / {
            if {Detexted-Locale} is "de-DE" {
                / /de/ 307
            }
            / /{>Detected-Locale}/ 307
        }
    }
}

Hi @markustenghamn, welcome to the Caddy community.

It looks like you’ve attempted to nest your if subdirectives. Generally speaking, directives in the Caddyfile are not nestable by design, in an attempt to keep Caddyfiles as flat as possible.

The docs for http.redir outline how you can chain multiple if statements:

if specifies a rewrite condition. Multiple ifs are AND-ed together by default.

So you could simply pair up your initial comparison with the secondary comparisons in two separate uses of redir. It would look like this:

redir {
	if {path} is /
	if {>Detected-Locale} is "de-DE"
	/ /de/ 307
}
redir {
	if {path} is /
	/ /{>Detected-Locale}/ 307
}

https://caddyserver.com/docs/redir

Thank you for the help. I tried something similar before I did the nested if statements and I still get the following error. This is after I replaced my redir with your two redir clauses.

Caddyfile:17 - Parse error: rule with duplicate 'from' value: / -> /de/

I could solve it with 2 redirects like so but I would prefer not to have to do this.

localhost:8080 {
    gzip
    log ./access.log
    tls self_signed

    locale en de de-DE {
      detect header
    }

    redir {
        if {path} is /de-DE/
        /de-DE/ /de/ 307
    }

    redir {
        if {path} is /
        / /{>Detected-Locale}/ 307
    }

}

Hmm, that’s annoying. Try with a rewrite instead. This will avoid redirecting the user twice.

rewrite {
	if {path} is /
	if {>Detected-Locale} is "de-DE"
	to /redir-de/
}
redir /redir-de/ /de/

redir {
	if {path} is /
	/ /{>Detected-Locale}/ 307
}
1 Like

Nice, that works!

I’ve encountered a similar issue on one of my sites recently; will probably be looking into a better way to do that soon.

Ran into something similar:

  redir {
    if_op or
    if {path} starts_with /boards/
    if {path} starts_with /projects/
    / https://jeelabs.net{uri}
  }

  redir {
    if {path} match ^/(\w\w)\d(.html)?$
    / https://jeelabs.net/projects/hardware/wiki/{1}
  }

Which gives a similar Parse error: rule with duplicate 'from' value: / -> ... error. Will try a rewrite as suggested in this thread, but it does feel a bit like a kludge to have to introduce an artificial base path, only to redirect it right afterwards.

To follow up, this pattern appears to work well for fixed prefixes:

  rewrite {
    if {path} starts_with /boards/
    to /boards/
  }
  redir /boards/ https://jeelabs.net{uri}

In other words: strip the tail in the rewrite and add it back in with the redirect.

2 Likes

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