NGINX capture variable in location and use it in rewrite and proxy_redirect

I am facing a problem building on top of my other question (NGINX reverse proxy rewrite rule with proxy_redirect)

Now I want to achieve the following. "https://mydemo.app.de/test1/", "https://mydemo.app.de/test2/" or "https://mydemo.app.de/test3/" should all be rewritten (not redirected) to "http://mydemo.app.local/target/" So basically a user entering test1,2 or 3 should get the content from target without an URL change.

I have this working, but without the OR condition. This is my working configuration.

    location ~* /test1 {
        rewrite (?i)/test1(.*) /target$1 break;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;

        proxy_pass http://mydemo.app.local;
        # The location header in the servers response sometimes contains "ReturnURL=xyz" at the end. Therefore we need to catch and rewrite this occurance twice.
        proxy_redirect ~*(.*)/target/(.*)target(.*)$ https://mydemo.app.de/test1/$2/test1/$3;
        #This rule only gets used if there is no "ReturnURL=xyz" at the end of the location header in the servers response
        proxy_redirect ~*(.*)/target/(.*)$ https://mydemo.app.de/test1/$2;

This is what I came up with so far.

location ~* /(?<systemname>(test1|test2|test3)) {

        rewrite (?i)/$systemname(.*) /target$1 break;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;

        proxy_pass http://mydemo.app.local;
        # The location header in the servers response sometimes contains "ReturnURL=xyz" at the end. Therefore we need to catch and rewrite this occurance twice.
        proxy_redirect ~*(.*)/target/(.*)target(.*)$ https://mydemo.app.de/$systemname/$2/$systemname/$3;
        #This rule only gets used if there is no "ReturnURL=xyz" at the end of the location header in the servers response
        proxy_redirect ~*(.*)/target/(.*)$ https://mydemo.app.de/$systemname/$2;
        proxy_pass_header Server;

But sadly it results in http://mydemo.app.local/test1 instead of http://mydemo.app.local/target

I'm trying to reduce the lines of code here. I could use 3 locations, but 95% of the location is the same code. This would only blow up my config file.

I'm at the end of my wits. Hopefully someone is able to shed some light here. Thanks in advance.


Solution 1:

You can't use variables inside the regex patterns, all the regex patterns are compiled at the nginx startup, although you are free to use variables inside the strings that to be matched upon some regex pattern. This means the $systemname variable won't be evaluated when you use the

rewrite (?i)/$systemname(.*) /target$1 break;

Your location ~* /(?<systemname>(test1|test2|test3)) { ... } gets both the $systemname and the $1 variables populated, it is sufficient to use simply the location ~* /(?<systemname>test1|test2|test3) { ... }. If you expect that (test1|test2|test3) names only at the beginning of the URI, you can use

location ~* ^/(?<systemname>test1|test2|test3)(?<route>.*) {
    rewrite ^ /target$route break;
    ...
}

since no other request would be captured by this location.