skip to Main Content

I have an app on a domain that is set by a developer to proxy at certain URLs:

example.com/browser/123foo0/stuff.js

for example, where 123foo0 is some random key. The key may also change length in future.

That’s all fine.

But I’d like to interrupt specific requests and not proxy them: I don’t want to serve anything after the key that is in the path /welcome for example, i.e. not proxy any of these:

example.com/browser/123foo0/welcome/welcome.html
example.com/browser/foo456b/welcome/welcome.css
example.com/browser/bar123f/welcome/welcome.js
example.com/browser/456foob/welcome/other.stuff
example.com/browser/foo789b/welcome/

So I tried simple stuff first like: location ^~ /browser/.*/welcome/welcome.html {... and location ~* .*/welcome/ {...
but couldn’t even get that working, before moving on to try capturing groups like css files and scripts and so on.

I also tried putting regex in quotes, but that didn’t seem to work either.

What am I doing wrong?

Here’s a truncated version of the conf, with the location blocks only:

    location ^~ "/browser/.*/welcome/welcome.html" {
        return 200 'Not proxied.n';
        add_header Content-Type text/plain;
    }

    location ^~ /browser {
        proxy_pass http://127.0.0.1:1234;
        proxy_set_header Host $http_host;
    }

    # landing page
    location / {
      root /var/www/foobar;
      index index.html;
      try_files $uri $uri/ /index.html;
    }

Edit

I’ve reviewed the documentation on how nginx selects a location, but unfortunately I didn’t find it particularly clear or helpful. What am I missing?

I thought this rule in question would match and take precedence over the latter /browser rule, because of this line in the documentation:

If the longest matching prefix location has the “^~” modifier then regular expressions are not checked.

i.e. because this rule in question comes first and it is longer than the latter /browser rule, a match would occur here and not later (because processing stops here)?

But this is also confusing because I also tried ~* [pattern] instead of the priority prefix ^~ [pattern] and that didn’t work either…

2

Answers


  1. # 1 regexp location
    location ~ ^/browser/.*/welcome/.*$ {
      return 200 'Not proxied.n';
      add_header Content-Type text/plain;
    }
    # 2 regexp location
    location ~ ^/browser/.* {
      proxy_pass http://127.0.0.1:3003;
    }
    =========================================
    server {
      listen 3003;
    ...
      location ~ ^/browser/.*$ {
        return 200 'Proxied from $hostn';
        add_header Content-Type text/plain;
      }
    }
    

    check with curl

    $ curl http://127.0.0.1:3002/browser/KEY/notwelcome/some/path/file.ext
    Proxied from 127.0.0.1
    
    $ curl http://127.0.0.1:3002/browser/KEY/welcome/some/path/file.ext
    Not proxied.
    

    if you write location 1 some like

    location ~ ^/browser/.*/welcome/.*.(js|css)$
    

    check

    $ curl http://127.0.0.1:3002/browser/KEY/welcome/some/path/file.js
    Not proxied.
    
    $ curl http://127.0.0.1:3002/browser/KEY/welcome/some/path/file.txt
    Proxied from 127.0.0.1
    
    $ curl http://127.0.0.1:3002/browser/KEY/notwelcome/some/path/file.txt
    Proxied from 127.0.0.1
    

    if swap location 1 and 2 all request will match only with

    location ~ ^/browser/.* {
    

    and will be proxied

    $ curl http://127.0.0.1:3002/browser/KEY/some/path/file.css
    Proxied from 127.0.0.1
    $ curl http://127.0.0.1:3002/browser/KEY/welcome/asdfadfasdfas.txt
    Proxied from 127.0.0.1
    

    nginx docs
    Then regular expressions are checked, in the order of their appearance
    in the configuration file. The search of regular expressions
    terminates on the first match, and the corresponding configuration is
    used.

    Login or Signup to reply.
  2. You have:

    location ^~ "/browser/.*/welcome/welcome.html" { ... }
    location ^~ /browser { ... }
    

    which is wrong in two ways:

    1. /browser/.*/welcome/welcome.html is a regular expression (because of the .*), which means it can only appear in location statements with a ~ or ~* operators.

    2. location ^~ /browser will allow a longer matching prefix location, but you cannot use a prefix location because of the .*.


    A better solution would be:

    location ~ ^/browser/[^/]+/welcome/welcome.html$ { ... }
    location /browser { ... }
    

    By using the corrected regular expression statement, and removing the ^~ operator from the prefix location.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search