Nginx if $arg rule 404ing requests, why? - nginx

I have written the following rule in a nginx server block:
location /s/sport(/)$ {
if ($args ~ country){
rewrite ^(.*) /s/sport/country/$arg_country? break;
}
}
The goal here is to transform legacy URLs such as http://example.com/rankings/soccer?country=de to http://example.com/rankings/soccer/country/de. This could of course be implemented in the app itself, but we need to do it before hitting the app for performance reasons; these URLs break our caching strategy.
The trouble is when this rule is applied, the following URL formats start to 404:
/s/sport
/s/sport?country={iso_code}
/s/sport/country/{iso_code}
nginx reports that the request failed (2: No such file or directory) which leads me to believe that it is now looking for a physical file with that name instead of passing the path to the app.
How do I fix the rule?
EDIT: Here's the full server config I'm trying to add on to:
server {
listen *:80;
server_name example.com;
passenger_enabled on;
access_log /path/to/app/logs/access.log main;
error_log /path/to/app/logs/error.log error;
root /path/to/app/current/public;
location ~* \.(ico|css|js|gif|jp?g|png|swf)(\?[0-9]+)?$ {
expires max;
break;
}
if (-f $document_root/maintenance.html) {
return 503;
}
error_page 503 #maintenance;
location #maintenance {
rewrite ^(.*)$ /maintenance.html break;
}
}

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 500 Internal Server Error rewrite or internal redirection cycle while processing

I am facing this issue of using API, could anyone help please?
When I use my API my web server shows me this and shows '500 Internal Server Error':
2022/02/24 21:40:46 [error] 381920#0: *50 rewrite or internal redirection cycle while processing "/wp-json/wc/v2/orders"
And here is my Nginx settings:
server
{
listen 80 default_server;
listen 443 ssl http2 default_server;
index index.php index.html index.htm default.php default.htm default.html;
if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}
include enable-php-74.conf;
location / {
if (!-e $request_filename) {
rewrite ^([_0-9a-zA-Z-]+)?(/wp-.*) $2 last;
rewrite ^([_0-9a-zA-Z-]+)?(/.*\.php)$ $2 last;
rewrite ^ /index.php last;
}
}
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
location ~ \.well-known{
allow all;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
}
Have been finding other settings to Nginx file but they didn't work.
Please give me a hand, thanks all!!

No Response on NGINX when using upstream

I'm trying to load balance a web application through nginx, It works fine for all will my web application calls a service with sub-path.
for example it works
http://example.com/luna/
but not for
http://example.com/luna/sales
My nginx.conf
user nobody;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream lunaups {
server myhostserver1.com:8080;
server myhostserver2.com:8080;
}
server {
listen 80;
server_name example.com;
proxy_pass_header Server;
location = / {
rewrite ^ http://example.com/luna redirect;
}
location /luna {
rewrite ^$/luna/(.*)/^ /$1 redirect;
proxy_pass http://lunaups;
#add_header X-Upstream $upstream_addr;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
my web application calls a service with additional subpath like /luna/sales fails to return response. What am i missing here?
It works if i remove one of my host server from upstream, But when I add second host on upstream it fails to return response.
Is my rewrite rule wrong or my configurations as whole is wrong?
There are four suffixes to the rewrite directive and they all have specific uses. See this document for details.
If you want the URI / to be mapped to /luna without changing the URL in the browser, you would use an internal rewrite with rewrite ... last. For example:
location = / {
rewrite ^ /luna last;
}
In the location /luna block, you need to rewrite the URI before sending it to proxy_pass statement (without leaving the location block), which requires a rewrite ... break. For example:
location /luna {
rewrite ^/luna(/.*)$ $1 break;
rewrite ^ / break;
proxy_pass http://lunaups;
}
The first rewrite changes any URI with a sub-path, and the second rewrite handles the URI without a sub-path.
See this useful resource on regular expressions.

Why is my nginx "rewrite" directive causing a redirection loop?

Given the following http block, nginx performs as expected. That is, it will rewrite a URL such as http://localhost/3ba48599-8be8-4326-8bd0-1ac6591c2041/ to http://localhost/modif/3ba48599-8be8-4326-8bd0-1ac6591c2041/ and pass it to the uwsgi server.
http {
upstream frontend {
server frontend:8000;
}
server {
listen 8000;
server_name localhost;
root /www/;
location ~* "^/([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})/?$" {
include uwsgi_params;
set $uuid $1;
if ($cookie_admin) {
# if cookie exists, rewrite /<uuid> to /modif/<uuid> and pass to uwsgi
rewrite / /modif/$uuid break;
uwsgi_pass frontend;
}
content_by_lua_block {
ngx.say("Ping! You got here because you have no cookies!")
}
}
}
}
However, when I add another location block in the manner displayed blow, things fall appart and I get ERR_TOO_MANY_REDIRECTS.
http {
# access_log /dev/stdout; # so we can `docker log` it.
upstream frontend {
server frontend:8000;
}
server {
listen 8000;
server_name localhost;
root /www/;
location / { # THIS MAKES EVERYTHING FALL APART :(
uwsgi_pass frontend;
include uwsgi_params;
}
location ~* "^/([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})/?$" {
include uwsgi_params;
set $uuid $1;
if ($cookie_admin) {
# if cookie exists, rewrite /<uuid> to /modif/<uuid> and pass to uwsgi
rewrite / /modif/$uuid break;
uwsgi_pass frontend;
}
content_by_lua_block {
ngx.say("Ping! You got here because you have no cookies!")
}
}
}
}
What's going on here, exactly? How can I fix this?
I see your Nginx is listening on port 8000, but your upstream server is at 'frontend', also on port 8000. If frontend resolves to the same server that Nginx is running on, then you've got a loop of proxy requests happening.

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