“proxy_pass” cannot have URI part in location give

2020-02-12 10:20发布

问题:

I've developed a URL shortening web application.

It consists of two separate docker containers: one containing the backend REST api and another containing the frontend static website.

These two containers are linked to an nginx container. The configuration for this nginx container is below:

worker_processes 1;

events { worker_connections 1024; }

http {
    upstream api {
        server short-url:8080;
    }

    upstream frontend {
        server short-url-frontend:8081;
    }

    gzip on;
    gzip_vary on;
    gzip_min_length 860;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css text/xml application/javascript application/x-javascript application/xml;
    gzip_disable "MSIE [1-6]\.";

    server {
        listen 80;
        root    /user/share/nginx/html;

        location /urlshortener/v1 {
            proxy_pass         http://api/urlshortener/v1;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
        }

        location ~ ^/([A-Za-z0-9]+) {
            rewrite ^/([A-Za-z0-9]+) /$1
            proxy_pass         http://api/urlshortener/v1;
        }

        location / {
            proxy_pass          http://frontend;
            proxy_set_header    Host              $host;
            proxy_set_header    X-Real-IP         $remote_addr;
            proxy_set_header    X-Forwarded-for   $remote_addr;
        }
    }

}

If a url ends with /urlshortening/v1, I'm proxying to the backend.

If a url starts with /, I'm proxying to the frontend.

Shortened urls e.g. /3xTy or /a0q need to be proxied to the backend so that the user can be navigated to the original url. In order to do this, I've defined a location with a regular expression.

location ~ ^/([A-Za-z0-9]+) {
    rewrite ^/([A-Za-z0-9]+) /$1
   proxy_pass         http://api/urlshortener/v1;
}

This block of code gives me the following error:

2018/11/17 16:47:03 [emerg] 1#1: "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/nginx.conf:36

I've gone through several examples and reviewed a number of answers and I believe that the configuration I have should work. Can someone please explain why I'm getting this error?

回答1:

If you use a URI with a proxy_pass statement within a regular expression location, you need to build the entire URI using one or more variables. See this document for details.

So the alternatives are to (1), capture the URI from the location expression and add it to the proxy_pass statement. For example:

location ~ ^/([A-Za-z0-9]+) {
    proxy_pass http://api/urlshortener/v1/$1;
}

Or (2), use proxy_pass without a URI part, and construct the desired URI using a rewrite...break. For example:

location ~ ^/([A-Za-z0-9]+) {
    rewrite ^/([A-Za-z0-9]+) /urlshortener/v1/$1 break; 
    proxy_pass http://api;
}

See this document for details.



标签: nginx