String-manipulation in redir possible?


(Maciej świć) #1

Hi,
I have some very similar redirects in many places that i would like to make a bit more generic by replacing with an include. This would require substr() or something similar on the {host} placeholder. Is this possible?

Current

redir 302 {
    if {remote} starts_with "10.0"
    / https://service.domain.com{uri}
} 

What i want

redir 302 {
    if {remote} starts_with "10.0"
    / https://substr({host},2){uri} #Remove 2 first letters from the {host}
}

The idea is that if i had a https://e-service.domain.com tab open on my phone while out and return to home, it redirects to https://service.domain.com which doesn’t require authentication.


(Matthew Fay) #2

Hi @maciekish,

Sorry to say, but there is no functionality to configure string manipulation of placeholders.

Could I ask what the use case would be? Specifically, if you’re intending to use this as a generic redirect for more than one site definition, how would you structure that to avoid having to hardcode the destination hostnames as site labels anyway?


(Maciej świć) #3

I do indeed have labels hardcoded, but this would enable to make one “redirect” label for all of the sites.

Example, all reverse proxies:

service1.domain.com
service2.domain.com
service3.domain.com
e-service1.domain.com
e-service2.domain.com
e-service3.domain.com

The sites without e- (as in external) are only accessible from the local network and redirect to e- when accessed from the outside. When e- sites are accessed internally they are redirected to the non-e counterpart to avoid having to log in. If there was basic string manipulation i could just import redirect in each e-site and avioid 3 lines of config.

The current config:

(external) {
    redir 302 {
        if {remote} not_starts_with "10.0.0"
        if {remote} not_starts_with "10.0.1"
        if {remote} not_starts_with "10.0.2"
        if {remote} not_starts_with "10.0.3"
        / https://e-{host}{uri}
    }
}

(router) {
    proxy / https://10.0.0.1 {
        transparent
        websocket
        insecure_skip_verify
    }
}

router.domain.com {
    import options
    import external
    import router
}

e-router.domain.com {
    import auth
    import options

    redir 302 {
        if {remote} starts_with "10.0"
        / https://router.domain.com{uri}
    }

    import router
}

Would become:

(external) {
    redir 302 {
        if {remote} not_starts_with "10.0.0"
        if {remote} not_starts_with "10.0.1"
        if {remote} not_starts_with "10.0.2"
        if {remote} not_starts_with "10.0.3"
        / https://e-{host}{uri}
    }
}

(internal) {
    redir 302 {
        if {remote} starts_with "10.0"
        / https://{host,2}{uri}
    }
}

(router) {
    proxy / https://10.0.0.1 {
        transparent
        websocket
        insecure_skip_verify
    }
}

router.domain.com {
    import options
    import external
    import router
}

e-router.domain.com {
    import auth
    import options
    import router
}

(Matthew Fay) #4

Ahh, gotcha. Sorry I couldn’t bring you a better answer.

There’s a heavily work-in-progress PR over at the Github page for Caddyfile-wide “if” statements which might possibly one day support arbitrarily extracting this information via regex.

https://github.com/mholt/caddy/pull/1948


(Maciej świć) #5

Wider if-support would make this even simpler and not require substring as i would hopefully be able to puth the auth in an if based on client ip.