Convert 3 redirect rules into one - nginx

A proxy app proxies to other apps with some regex in the location blocks of the nginx.conf. For example to a signup app called proxy-signup-app.
This works, but it has 3 location blocks:
location ~* ^/signup/(.*)/$ {
proxy_pass https://proxy-signup-app.herokuapp.com/?proxy_regex=$1;
}
location ~* ^/signup/(.*)$ {
proxy_pass https://proxy-signup-app.herokuapp.com/?proxy_regex=$1;
}
location ~* ^/signup$ {
proxy_pass https://proxy-signup-app.herokuapp.com/?proxy_regex=$1;
}
It should proxy
/signup
/signup/
/signup/rainyday
/signup/rainyday/
Where the proxy app would receive on proxy_regex:
$1 = ''
$1 = ''
$1 = 'rainyday'
$1 = 'rainyday' (not /rainyday/, rainyday/ or /rainyday)
It should not redirect
/signups
How to merge these location blocks into one?

not sure if it's the best way, but it should work
location ~* ^/signup(/(.*?)/?|)$ {
proxy_pass https://proxy-signup-app.herokuapp.com/?proxy_regex=$2;
}

Related

NGINX Location matching wrong similar location

We are migrating off an old api onto a new api. We will eventually update the front end code but for now are doing it in nginx.
#location /vapi {
# old api
location ~ ^/vapi/(?!(sites))/.+$ {
add_header Access-Control-Allow-Origin $cors_header;
access_log logs/vapi.proxy.log lfupstream;
error_log logs/vapi.error.log error;
rewrite ^/vapi/(.*)$ /$1 break;
proxy_pass http://vapi;
}
# new api
location ~ ^/vapi/sites/.+$ {
add_header Access-Control-Allow-Origin $cors_header;
access_log logs/vapi.portal.proxy.log lfupstream;
error_log logs/vapi.portal.error.log error;
rewrite ^(.*)$ /api/$1 break;
proxy_pass https://portal;
}
The old api is matching https://exa.valor.network/vapi/sites/SITE-NAME Have also tried:
location /vapi {
...
}
location /vapi/sites {
...
}
and
location /vapi {
...
}
location ~^/vapi/sites/.+$ {
...
}
Ref: Nginx location "not equal to" regex
Ref: Nginx location priority
Beside the fact I was on a test nginx and not the dev nginx Richard Smith's comment was a solution that worked. I had misread how nginx selected regex location as the longest had the highest priority. I ended up going with a regex for the new api and left the old api as is with a Prefix match thus the new api location takes priority if matched otherwise the old api gets the match.
Thanks to Richard Smith.
# new api
location ^~ /vapi/sites {
rewrite ^/(.*)$ /api/$1 break;
proxy_pass https://portal;
}
# old api
location /vapi {
rewrite ^/vapi/(.*)$ /$1 break;
proxy_pass http://$vapi_service;
}

Nginx same location 2 blocks with diffrent proxy pass

Trying to configure nginx to have 2 proxy passes for the same location.
Example:
domain.com to go to the homepage proxy
domain.com/user to go to user profile proxy
What i need to do:
What I tryed:
location = / { proxy_pass http://home_page; }
location ~ ^/(.+) { proxy_pass http://user_profile_page; }
If I go to domain.com/ and domain.com/username it goes to the same proxy.
I have to mention that the config has also the /auth location block with exact match "="
that has domain.com/auth, domain.com/auth/login. This location block works as expected
location ^~ /auth { proxy_pass http://auth_page; }

Nginx an application redirects on root site

Navigate to localhost/app1 redirects me on localhost/login, expected - localhost/app1/login.
Is it possible to change the application redirect to the right place using nginx?
location /app1/ {
proxy_pass http://localhost:8080/;
}
Used Referer URL to make the right way redirection. The configs below:
nginx.conf - get application name from $http_referer
http {
map $http_referer $app {
~*//[a-z0-9_.-]+/([a-z0-9_.-]+) $1;
}...
}
root.conf - redirect wrong URLs to $app$uri
location / {
if ($http_referer != "") {
rewrite ^(.*)$ /$app$uri redirect;
}
app1.conf - important! The Referer header must be added!
location /app1/ {
proxy_pass http://localhost:8080/;
proxy_set_header Referer $http_referer;
...
}

Nginx rewrite not redirecting

I would like to rebuild a URL and redirect from https://test.com/info/schoolName/detail to https://test.com/school-info?name=schoolName with Nginx.
I have tried
location ~ ^/(school-info)(?:/(.*))?$ {
include /etc/nginx/servers/platform/shared/headers_proxy.conf;
proxy_set_header Host $backend_netlify_main;
proxy_ssl_server_name on;
proxy_pass https://$backend_netlify_main/$1/$2;
}
...
...
location ~* ^/(info|info/)$ {
include /etc/nginx/servers/platform/shared/headers_proxy.conf;
rewrite ^/info/(.?)/(.*)$ /school-info?school=$1 permanent;
proxy_pass $backend_cms;
}
however, if I visit https://test.com/info/byu/detail it's not doing a redirect at all.
EDIT: The /detail at the end is not important at all, so regardless of what is at the end of the URL the /schoolName/ is the most important part to be passed as a query parameter.
I think you need something like
location / { # "default" location
# do redirection for '/info/...' URIs
rewrite ^/info/([^/])* /school-info/$1 permanent;
# otherwise pass request to the default backend
proxy_pass $backend_cms;
}
location /school-info {
include /etc/nginx/servers/platform/shared/headers_proxy.conf;
proxy_set_header Host $backend_netlify_main;
proxy_ssl_server_name on;
proxy_pass https://$backend_netlify_main;
}
if you need to pass a request as /school-info/schoolName, or
location / { # "default" location
# do redirection for '/info/...' URIs
rewrite ^/info/([^/])* /school-info?name=$1 permanent;
# otherwise pass request to the default backend
proxy_pass $backend_cms;
}
location /school-info {
include /etc/nginx/servers/platform/shared/headers_proxy.conf;
proxy_set_header Host $backend_netlify_main;
proxy_ssl_server_name on;
proxy_pass https://$backend_netlify_main/school-info$is_args$args;
}
if you need to pass a request as /school-info?name=schoolName.

Is is possible to define a single nginx location in two separate blocks?

Is is possible to define a single nginx location in two separate blocks?
For example:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
# What do I need to do to get this second root location
# to append to the 1st? If it's even possible.
location / {
proxy_pass http://foo;
}
}
The idea is that the root location then effectively becomes:
location / {
proxy_cache off;
proxy_pass http://foo;
}
If you'd like to know more about the why, read on.
Background:
I'm running a GitLab Omnibus installation. According to the docs, an admin an inject custom nginx config to the GitLab server block.
However, this injection adds things to the end server block rather than a specific location block.
So if I try to inject include my_config.conf;, I'll get:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
include my_config.conf;
}
and if I try to include location ^~ / {\n include my_config.conf;\n }\n I'll get:
server {
listen *:80;
server_name someserver;
location / {
proxy_cache off;
}
location /assets {
proxy_cache mycache;
}
location ^~ / {
include my_config.conf;
}
}
which then causes the nginx config to fail with a duplicate location "/" in /var/opt/gitlab/nginx/conf/gitlab-http.conf:106 error.
Note: my_config.conf contains add_header stuff for CORS, so it needs to be in a location block.
You probably need to understand how nginx processes a request. But location blocks are not additive and must be individually complete. You can place certain statements in the server block and allow individual location blocks to override as required (e.g. proxy_cache).
Assuming that all of your URIs are proxied, you could use something like this:
proxy_cache off;
location / {
proxy_pass http://foo;
}
location /assets {
proxy_cache mycache;
proxy_pass http://foo;
}
Common statements can be offloaded to an include file.

Resources