Jayden
Jayden

Reputation: 79

Nginx rewrite url path to add prefix of path

I am working with my nginx server and I have no idea how to add /api prefix to the existing url.

I have two endpoints /api/deepzoom and /api/detection exposed by Flask. I don't want to change the code in frontend that call /deepzoom and /detection yet.

How can I rewrite/redirect the url path to /api/deepzoom when called from frontend with /deepzoom

My current snippet in nginx.conf:

upstream platform {
    server platform:5001;
}
upstream models {
    server models:4999;
}

upstream deepzoom {
    server deepzoom:5999;
}

server {
    listen 80 ;
    server_name  myhost.mydomain.com;

    client_max_body_size    0;
    client_body_buffer_size 1m;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   Host $host:$server_port;
    proxy_set_header   X-Real-IP  $remote_addr;
    send_timeout       10m;
    proxy_buffer_size 512k;
    proxy_buffers 4 1024k;
    proxy_busy_buffers_size 1024k;
    proxy_redirect off;

location ^~ /api/detection/ {
    include uwsgi_params;
    proxy_pass    http://models;
}

location ^~ /api/deepzoom/ {
    include uwsgi_params;
    proxy_pass    http://deepzoom;
}
location  / {
    include uwsgi_params;
    proxy_pass         http://platform;

    }
 }

I have tried to add the lines in server block:

rewrite ^ /detection/ http://$server_name/api/detection/$1 permanent;
rewrite ^ /deepzoom/ http://$server_name/api/deepzoom/$1 permanent;

but it doesn't work with 404 Not Found error.

Anyone can help me to figure it out and how to satisfy the requirement. Thanks!

Upvotes: 5

Views: 29435

Answers (2)

takanuva15
takanuva15

Reputation: 1678

I found this question while trying to add a prefix to the path for a React app I'm running in front of nginx. I wanted all requests to the app to have the prefix /mypref because my app files were in a subdirectory called /mypref. If a url already started with /mypref, I wanted to "forward" the remaining part of the url to index.html so it could be handled by react-router. The following nginx configuration did the trick for me:

# redirect requests not matching /mypref so that they start with /mypref/...
location / {
  absolute_redirect off;
  return 301 /mypref$request_uri;
}

# This config allows access to nested routes directly.
# Example: Without this, if you accessed https://myapp.com/mypref/my-requests directly, it
# would fail. You would need to access https://myapp.com/mypref/ first, and then navigate to
# the nested route.
# With this config in place, you can go to the nested route and anything after /mypref/ automatically gets passed to
# the index file so that it can be handled by react-router
location /mypref {
  absolute_redirect off;
  if (!-e $request_filename) {
    rewrite ^(.*)$ /mypref/ break;
  }
  index index.html index.htm Default.htm;
}

I used relative redirects here since my app was in front of a gateway and I didn't want users leaving the gateway.

Upvotes: 0

Richard Smith
Richard Smith

Reputation: 49702

The rewrite...permanent statements in your question are badly formed and do not perform the function you require.

  • permanent causes a redirection with a 301 response
  • there is space between the ^ and / characters
  • there are no parentheses to capture the value of $1

To internally rewrite the URI before passing it upstream, you can use rewrite...last. See this document for details.

For example:

rewrite ^(/(detection|deepzoom)(/.*)?)$ /api$1 last;
location ^~ /api/detection { ... }
location ^~ /api/deepzoom { ... }

Note, if your endpoint is /api/deepzoom, then you do not want a trailing / on your location value.


You can achieve a similar behaviour using the proxy_pass directive. See this document for details.

For example:

location ^~ /deepzoom {
    include     uwsgi_params;
    proxy_pass  http://deepzoom/api/deepzoom;
}

Take care that both the location and proxy_pass values have a trailing / or neither have a trailing /.

Upvotes: 10

Related Questions