Can you migrate a web app available via '/' to a proxied sub-URI without modifying the web app?

Francis Daly francis at daoine.org
Tue May 9 12:37:19 UTC 2017


On Mon, May 08, 2017 at 06:17:02PM -0500, deoren wrote:

Hi there,

> I'm still
> not completely clear on whether this is supported.

nginx does the nginx side as much as it can. Whether it all works is
almost entirely down to the web app.

You cannot reliably reverse-proxy an arbitrary web app to a different
place in the url hierarchy than that at which it believes it is installed.

You can unreliably do it, if that is good enough for you.

> #2) I'd like to move the web application to
> https://subdomain.example.com/sub-uri/ by setting up location block
> like so (spacing condensed for display purposes):
> 
>     location /flask-demo {
>         root /var/www/passenger-python-flask-demo;
>         proxy_set_header X-Forwarded-Proto $scheme;
>         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
>         proxy_set_header X-Forwarded-Host $host;
>         proxy_pass http://127.0.0.1:3000/;
>     }
> 
> The trailing slash was added in an attempt to map
> /flask-demo/SOMETHING to /SOMETHING in the application's point of
> view.

Just as a small point -- it is usually worth making sure that the numbers
of / characters at the end of the "proxy_pass" argument and at the end
of the "location" prefix value, are the same.

> That works well for a test web app where everything is contained in
> a single file, but when the static assets are referenced by the HTML
> output the user's browser attempts to pull static content from '/'
> instead of '/flask-demo/'.

I would suggest that the HTML output of the web app is wrong.

It should never link to /static/styles.css, if it wants to be
reverse-proxied.

It should link to static/styles.css or to ../static/styles.css or to
../../static/styles.css or to whatever value is appropriate relative to
the current resource.

If the web app did that, then reverse-proxying would probably Just Work.

"Not wanting to be reverse-proxied" is a valid choice for a web app. And
you can choose not to use ones that make that choice.

> I'm hoping there is a way to isolate each web application based on
> the initial location block match, thereby catching follow-up
> requests for static resources related to the first request and
> prepend the sub-URI.

In http, every request is independent of every other request, unless
you do something to try to tie them together (such as with a Cookie).

Stock nginx will receive a request for /static/styles.css, and will
handle it according to its configuration.

If you want your nginx to receive a request for /static/styles.css, and
to do some processing based on the Referer: header or based on a Cookie:
header or something else, in order that the final processed request will
be /flask-demo/static/styles.css, then you will probably have to write
some code in one of the embedded languages in nginx.conf.

I'm not aware of code like that existing.

> I assume the answer is "no, this is not supported", but I wanted to

If you write the code, you can make it work (unreliably) for you.

It cannot work in stock nginx just using nginx.conf normal directives.

> ask just to make sure I'm not overlooking something. Francis Daly's
> remarks on the "URL-Rewriting not working" thread that I've quoted
> from below seems to suggest it might be possible, but probably isn't
> worth the headache:

Your outline above is that nginx should not do the translation in the
html sent to the client, but that nginx should interpret the following
requests based on something not directly specified in the request line.

That is possibly harder than doing the translation in the html.

> > That is, if you want the back-end / to correspond to
> > the front-end /x/, then if the back-end ever links to
> > something like /a, you will need that to become
> > translated to /x/a before it leaves the front-end. In
> > general, the front-end cannot do that translation.

You can try to get the front-end to do that translation; it will also
be unreliable and probably inefficient.

Basically, any text that the client might interpret as a url that starts
with http:// or https:// or / would potentially have to be modified. And
possibly some other text as well, depending on the exact contents.

> > So you may find it easier to configure the back-end to
> > be (or to act as if it is) installed below /x/ directly.

That is still true.

If you won't do that, and if you have two web apps that each want to
be at /, you may be better off having two server{} blocks in nginx with
different server_name values.

> I found the 'proxy_redirect' directive, but it doesn't appear to do
> what I'm looking for.

proxy_redirect deals with http headers, not with the body content.

> I've used nginx for years, but only in very basic configurations.
> This is something new to me and I'm struggling to wrap my head
> around it. Thank you for reading this and any advice you can offer.

It's a http and url thing, rather than an nginx thing.

Good luck with it,

	f
-- 
Francis Daly        francis at daoine.org


More information about the nginx mailing list