Can Nginx insert a missing "/" or missing "/bla/" in a URL? - nginx

Looking through the error.log file of Nginx, we can see requests coming as one of two incorrect patterns:
http://www.example.com/app-contextmoduleA/controller1 -> should be http://www.example.com/app-context/moduleA/controller1
http://www.example.com/app-contextcontroller2 -> should be http://www.example.com/app-context/moduleB/controller2
The current Nginx configuration looks like this:
server {
listen 8080;
location /app-context/ {
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://localhost:8888/app-context/;
}
}
The challenge is inserting the missing / after app-context (for the first wrong URL) or missing /moduleB/ (for the second wrong URL). It doesn't look like try_files would support that, and I have not found a way to do it with rewrite.
Is there a way for Nginx to rewrite the URLs for both use cases? In particular, I would prefer not to have to know all the name of the modules or controllers in advance. There are many, so "hard-coding" them in the rewrite rule would be onerous.

These should handle your example case:
location /app-context {
rewrite ^(/app-contextmoduleA)/(.*)$ /app-context/moduleA/$2 permanent;
rewrite ^(/app-contextcontroller2) /app-context/moduleB/controller2 permanent;
...
}
Check the ngx_http_rewrite_module for more info.

Looking through quite a few online resources and through trial and error, I was able to come to a good-enough solution:
location /app-context {
location ~ (moduleA|moduleB) {
# inserts a forward slash after app-context if not there,
# e.g. /app-contextmoduleA/foo/bar to /app-context/moduleA/foo/bar
rewrite ^(/app-context(?!/))(.*) $1/$2 break;
try_files $uri #proxy;
}
# inserts /defaultModule/ after app-context
# e.g. /app-context/controller1 to /app-context/defaultModule/controller1
rewrite ^(/app-context(?!/defaultModule/))(.*) $1/defaultModule/$2 break;
try_files $uri #proxy;
}
location #proxy {
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://localhost:8888;
}

Related

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.

Nginx location / overrides all other locations

I'm trying to write a simple nginx config. What I need is:
if file exists in root serve this file
If url is /default/url then show /some/path2/index.html
Otherwise redirect to /default/url
my config is as follows
server {
listen 127.0.0.1:80;
server_name my.domain.com;
root /some/path/html;
location / {
return 302 /default/url;
}
location = /default/url {
rewrite ^/(.*)$/some/path2/index.html;
}
location /default/e_schema {
proxy_pass http://other.host.com;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
It redirects to /default/url instantly regardless of url.
I was trying to put the location / block on the bottom and on the top. I've tried to use location ~ /.* to lower priority but nothing helps. If I remove location / at all everything is fine my requirements 2 and 3 is ok.
According to this answer https://serverfault.com/questions/656628/nginx-catch-all-other-locations-than-given/656634 it should work.
You have put an "=" in the location block
location = /default/url {
Could you try removing this? I believe it may be setting the url
The problem was here
location = /default/url {
rewrite ^/(.*)$/some/path2/index.html;
}
this makes internal redirect to /some/path2/index.html which is within / path so it triggers the location / block which redirects to /default/url and so on.
My solution was to make empty block to exclude the path from location /
location /some/path2/index.html {}

Rewrite and "host" urls on own domain

If i go to site https://example.com/media/https://google.com/imageurl
I want that the url openes the site after /media.
So i want to open https://google.com/imageurl but not a complete redirect.
It must stay on my domain, is that working?
I tried something like that, but not working :/
rewrite ^/media/(.*).(png|jpg|gif) $1.$2 ;
So everything after /media/ i will display show on my own domain, is something that working?
What you want to do is calling "transparent proxying". You cannot do this with simple rewrite. You can try this:
location ~ ^/media/(?<proto>https?:)/+(?<domain>[^/]+)(?<subreq>/.+\.(?:png|jpg|gif))$ {
proxy_ssl_server_name on;
proxy_set_header Host $domain;
proxy_pass $proto//$domain$subreq;
}
or this:
location ~ ^/media/(?<proto>https?:)/+(?<domain>[^/]+)(?<subreq>/.+\.(?:png|jpg|gif))$ {
proxy_ssl_server_name on;
proxy_set_header Host $domain;
rewrite .* $subreq break;
proxy_pass $proto//$domain;
}
You will also need a resolver directive in your config to use this.

nginx proxy_pass to all pages

So I am using nginx to reverse proxy to another server. This wasn't serving static files, until I linked them in the location. The location block is super long, but looks similar to the code below. I'm sure that I'm doing this the wrong way, but it works, it's just tedious to write all the paths. I'm wondering if there's a better way.
location / {
proxy_pass www.example.com;
}
location /sytlesheet.css {
proxy_pass www.example.com/stylesheet.css;
}
location /page1 {
proxy_pass www.example.com/page1;
}
#this goes on and on
Is there a way to get everything past the '/' for example 'page1', and pass that to the proxy without manually typing it?
I'm hoping there's something a way to use a variable or something to link all the pages and resources with a single location block:
location / {
proxy_pass www.example.com;
}
location /$variable {
proxy_pass www.example.com/$variable;
}
Thanks!
You should use following code
location / {
# First attempt to serve request as file, then
# as directory, then fall back to proxy
try_files $uri $uri/ #proxy;
}
location #proxy {
proxy_pass www.example.com;
}
Check this out.
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://www.example.com;
}

Nginx redirect with rewrite

Assuming I want to redirect URIs like
http://server1:8081/test/admin/option?options
http://server1:8081/test/admin/option/suboption?options
http://server1:8081/test/admin/option/suboption/subsuboption?options
to
http://server2:8080/tomcat/admin/option?options
http://server2:8080/tomcat/admin/option/suboption?options
http://server2:8080/tomcat/admin/option/suboption/subsuboption?options
what nginx rules I have to use? I've tried the following but it doesn't work
location =/test/admin {
proxy_pass http://server2:8080/tomcat/admin;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Try something along these lines ..
location /test/admin {
rewrite ^/test/admin(.*)$ /tomcat/admin$1;
}
location /tomcat/admin {
internal;
proxy_pass http://server2:8080;
[…]
}
That is, rewrite the requests to "tomcat/admin" which you can optionally make open to internal requests only.
In that location block, you can then proxy passthe request.

Resources