Score:2

How to deal with hardcoded requests of a webapp when using path-based location blocks?

us flag

I am trying to create a reverse proxy route using nginx-proxy and docker for OpenTripPlanner (OTP) version 1.5.0 and 2.2.0 on the same machine.

If I have a simple location block like:

location /otp2 {
        proxy_pass http://127.0.0.1:8081;
    }

The majority of calls OTP makes gets passed on to the upstream server, however the OTP web-app also has some hardcoded calls to http://host/otp and http://host/images (not http://host/otp2/otp and http://host/otp2/images). As they don't match an nginx location block, they fail to resolve.

How can I ensure these calls get routed to the upstream server as well?

What I've tried

Regex + rewrite

After a lot of fiddling around I settled on:

location ~^/(otp2|otp|images) {          
        rewrite ^(/otp2)$ $1/ permanent;
        rewrite ^/(otp2)(.*) $2 break;
        rewrite ^/(otp)(.*) /$1$2 break;
        rewrite ^/(images)(.*) $1$2 break;                                                                                                                                                                           
        proxy_pass http://127.0.0.1:8081;
    }

This works, but this prevents me from running OTP version 1.5.0 next to it, as that binary also requests http://host/otp and http://host/images.

Additionally, every other web-app I would run on that host that would have a route to /images would probably be picked up by that location block.

Subdomain

I cannot make changes to the DNS, so (I assume) I can only do path-based location blocks, and not subdomains like otp2.host.com and otp1.host.com.

Separate location blocks

Per suggestion of one of the answerers I tried separate location blocks:

location /otp2 {
    proxy_pass http://127.0.0.1:8081/;
}

location /otp2/otp {
    proxy_pass http://127.0.0.1:8081/otp/;
}

location /otp2/images {
    proxy_pass http://127.0.0.1:8081/images/;
}

This partially works, but leaves a few unhandled OTP requests which breaks the application (the host of the form sub1.sub2.company.country is obfuscated in below screenshot):

cn flag
This kind of reverse proxy where the paths are different are a bit more difficult to manage. You need to change the URLs in forms, refferences to JS and CSS, Location: header etc. Some of them could be dinamically generated in JS. I think it is much easier to use a subdomain for each application.
Saaru Lindestøkke avatar
us flag
Would love to use a subdomain, but the IT servicedesk does not offer that (and does control the DNS).
cn flag
The RegEx for `rewrite ^/(otp)(.*) /$1$2 break;` should be ^/(otp)([^12]*) /$1$2 break;` In this way it doesn't match with `/otp1`. I replaced `.` which means any character with `[^12]` which means any character except `1` and `2`. Try to see if it makes any difference. Another way is not to have `/otp/` at all and use only `/otp1/` `/otp2/`
Score:0
by flag

Lets use separate location block to handle the specific hardcoded requests from OTP 1.5.0 and 2.2.0, try this config:

server {
    listen 80;
    server_name your_host_name;

    # For OTP 1.5.0
    location /otp1 {
        proxy_pass http://127.0.0.1:8080;
    }

    location /otp1/otp {
        proxy_pass http://127.0.0.1:8080/otp;
    }

    location /otp1/images {
        proxy_pass http://127.0.0.1:8080/images;
    }

    # For OTP 2.2.0
    location /otp2 {
        proxy_pass http://127.0.0.1:8081;
    }

    location /otp2/otp {
        proxy_pass http://127.0.0.1:8081/otp;
    }

    location /otp2/images {
        proxy_pass http://127.0.0.1:8081/images;
    }

    # Additional web-apps with /images path
    location /other-web-app/images {
        proxy_pass http://127.0.0.1:8082/images;
    }

    # Handle remaining OTP v2 requests
    location /otp {
        proxy_pass http://127.0.0.1:8081/otp;
    }

    location /images {
        proxy_pass http://127.0.0.1:8081/images;
    }
}
Saaru Lindestøkke avatar
us flag
Thanks for the suggestion, but that doesn't work unfortunately. If I visit `http://host/otp2` I get greeted by a message from the upstream OTP server that the path `/otp2` does not exist. By adding a trailing slash to that proxy pass directive (i.e. `proxy_pass http://127.0.0.1:8081/;`) that is fixed, but then I still have a few remaining OTP v2 requests that directly try to call `http://host/otp/etc...` and `http://host/images/etc...`. These request are not caught by the blocks `otp2/otp` and `otp2/images`: https://i.imgur.com/SgtcG5R.png (host is obfuscated).
Saxtheowl avatar
by flag
I modified my answer, try the new code I provided
Saaru Lindestøkke avatar
us flag
Thanks for the update, but doesn't the `/images` block catch all the images paths? So both from the OTP 1.5 as well as from OTP 2.2 (as well as any other app that tries to reach the images path)?
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.