Nginx resolves the wrong route - nginx

I have an nginx-based configuration, where the root of the domain should lead to a static page (a splash page) and anything else should be proxied to an internally accessible machine. The configuration looks roughly as follows:
server {
listen 80;
location = / {
root /var/www;
}
location ~ / {
location /robots.txt {
root /var/www;
}
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}
}
The problem is that if the second block of code exists, the first one stops being taken into consideration. In other words, nginx starts looking for an index.html file on the 9091 instance, which does not exist. If the proxy_pass block is commented, then the first part goes into effect.
As far as the documentation is concerned, this should not be the case. If the root of my domain is called, Nginx should stop searching after the first block, since it is explicit. Yet, this is not the case.
What should be done here? I do not want to merge the splash page code, with the rest.

Your config looks very weird, but there is no indication that it shouldn't work as you seem to intend.
Perhaps you could try something like this? Else, please provide your full configuration (perhaps your cut-down example is missing something important that we should know about).
server {
listen 80;
root /var/www;
location = / {
}
location = /index.html {
}
location = /robots.txt {
}
location / {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}
}

Try this:
Replace splash.html to your splash page filename.
# Set root directory for requests
root /var/www;
# Rewrite / to /splash.html
rewrite ^/$ /splash.html break;
location = /splash.html { }
location = /robots.txt { }
location ~* / {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}

I guess you have index directive somewhere and this is how index is works.
It should be noted that using an index file causes an internal redirect, and the request can be processed in a different location.
Your first location matches, but then index module cause internal redirect to /index.html and request ends up in second location block.
I would write something like this:
server {
listen 80;
root /var/www;
location = /index.html {
}
location = /robots.txt {
}
location / {
proxy_pass http://127.0.0.1:9091;
proxy_set_header Host $host;
}
}

Related

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 {}

NGINX: Convert URI path to query string

My goal is to convert all non / requests of my Nginx server to /?data={uri-path}.
I was trying with the following configuration:
server {
server_name example.com;
listen 80;
location = / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
alias /home/....;
expires $expires;
}
location / {
return 301 http://example.com/?data=$request_uri;
}
}
The problem is I end with an URI like this: http://example.com/?data=?data=?data=?data=?data=?data=
and the browser complains about lots of redirections.
Based on documentation, location = should have the priority but seems I'm doing something wrong.
And feedback is appreciated.
It depends on what location = / does.
If it points to a directory and that directory contains an index.html file, Nginx will internally rewrite the URI, then search for a location to process that revised request.
This will result in a redirection loop.
You could break the loop by adding another location block to handle the final URI, for example:
location = /index.html { root ...; }
If the location = / block is intended to proxy the request, then you are missing a proxy_pass statement.

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;
}

Modify $request_uri in Nginx

I have multiple apps running on the Nginx server:
http://example.com/app1/ctrl/view
http://example.com/app2/ctrl/view
...
I would like to assign these apps DNS like so:
http://app1.example.com
http://app2.example.com
...
For that I've tried the following server block:
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://example.com/app1/$request_uri;
}
}
If a user is not logged in, my app would redirect to URI:
app1/ctrl/user/login?_next=/app/ctrl/view
Essentially $request_uri becomes (Note doubled app1 instance):
app1/app1/ctrl/user/login?_next=/app/ctrl/view
Is there a convenient way to modify $request_uri or a better method to get around this problem?
EDIT1
It seems I've solved my problem with the following server block:
server {
listen 80;
server_name app1.example.com;
location / {
set $new_request_uri $request_uri;
if ($request_uri ~ ^/app1/(.+)$) {
set $new_request_uri $1;
}
proxy_pass http://example.com/app1/$new_request_uri;
}
}
If someone knows a better (or proper "Nginx") way to do this please don't hesitate to post an answer.
EDIT2
Based on the comments I've also tried the following:
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://example.com/app1/;
proxy_redirect /app1/ /;
}
location ~ ^/app1/(.+)$ {
return 301 http://$server_name/$1;
}
}
This one looks better on screen, as it eliminates app1 instance in the $request_uri part completely, but you must have two location blocks.
EDIT3
The most efficient way to solve my problem apparently is as shown in this config:
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://example.com/app1/;
proxy_redirect /app1/ /;
}
location /app1/ {
rewrite ^/app1(.+) $1 permanent;
}
}
This is due to the fact, that Nginx always tries to match the longest prefix first and then (if ^~ modifier is not present) starts sequentially processing regexes until the first regex match is found. Essentially this means that all regexes are processed on every request, regardless if any of these find a match, therefore it's better to have regexes inside location directives.
You don't need to go complex way. Solution is much simpler
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://app1.example.com/app1/;
}
location /app1/ {
proxy_pass http://app1.example.com/app1/;
# or
# rewrite ^/app1(.+) $1 permanent;
}
}
Nginx will take care of adding /app1/ to request and strip it from Location header.
See proxy_redirect directive.

nginx proxy_pass configuration

I need to proxy a couple of urls to different hosts. Actually, I'm using the same host with different port to test my nginx configuration. This is my virtual host definition:
server {
listen 8081;
server_name domain.com;
location /Plasmid/ {
proxy_pass http://localhost:8000/Plasmid/;
}
location /_community/ {
proxy_pass http://localhost:8082/comments_api/ ;
}
location / {
# rewrite cq_user_authenticated===(.*)/(.*)/iuuid=(.*)/commenti.html$ /Plasmid/comments/legacy/$3/$1 ;
# rewrite querystring===(.*)$ /Plasmid/comments/legacy/$1 ;
# rewrite cq_user_authenticated===([^&]*)&/.*uuid=([^/]*) /comments_api/legacy/$2 ;
# rewrite userdetails(.*) /Plasmid/comments/user_details ;
root html;
index index.html index.htm;
}
}
Of course my hosts file has mapping for the domain.com
When I call the url: http://domain.com:8081/Plasmid/default/page/12 I get an http 404
If I remove the second location from my configuration:
location /_community/ {
proxy_pass http://localhost:8082/comments_api/ ;
}
I get the resource I want, but some part are missed since the are hosted on a different platform:
[error] 1033#0: *1 open() "/usr/local/Cellar/nginx/1.2.6/html/_community/content
How can I resolve this issue?
Do a little change:
location ^~ /Plasmid/ {
proxy_pass http://localhost:8000/Plasmid/;
}
location ^~ /_comunity/ {
proxy_pass http://localhost:8082/comments_api/;
Why is that? Because ^~ means starts with and when you request for page:
http://domain.com:8081/Plasmid/default/page/12
it fit to that rule. In your configuration you are using no mark and something like this:
location /anylocation
and it looks like your nginx prefer rule
location / {
than
location /Plasmid
and
location /_comunity
because it's using root directive and searching for _community/content in html folder (as you get in error message).
In other words ^~ has greater priority than no mark. One thing that could also help is to add break directive after each proxy_pass directive;

Resources