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.
Related
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.
my nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
upstream app_servers {
server 127.0.0.1:5000;
server 127.0.0.1:5001;
}
server {
listen 6200;
server_name test;
add_header X-GG-Cache-Status $upstream_cache_status;
include rewrite.conf;
}
}
and my rewrite.conf in the same folder as that
location = / {
rewrite ^/some-custom-destination/?$ /destination/detail?id=33;
proxy_pass http: //app_servers;
proxy_intercept_errors on;
error_page 400 404 /;
error_page 500 502 503 504 /error.html;
location = /error.html {
root /etc/nginx/;
}
}
when I use nginx -s reload command getting that error : nginx: [emerg] unknown directive "location" in /etc/nginx/rewrite.conf:1
How can I fix that?
Help, please. Thank you.
Apart from the space in your proxy_pass directive, there is one more issue with your location block.
From the nginx documentation about nginx location directive (http://nginx.org/en/docs/http/ngx_http_core_module.html#location), you cannot have a nested location inside a location block “location = /”.
“Also, using the “=” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates. For example, if a “/” request happens frequently, defining “location = /” will speed up the processing of these requests, as search terminates right after the first comparison. Such a location cannot obviously contain nested locations.”
I'm using Nginx map directive in order to retrieve the value of an http param and put it into another variable that will be used to do a basic auth with an ldap server (using nginx-auth-ldap).
The problem is that, according to my debug log, my map always chooses the default value.
Here is my configuration:
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
map $args $groupe_ldap {
default "default_group";
include /opt/nginx/appli.conf;
}
ldap_server my_ldap_server {
url ldap://somehost:someport/ou=xxx,dc=yyy,....;
binddn "...";
binddn_passwd "...";
require group "cn=$groupe_ldap,...";
group_attribute member;
group_attribute_is_dn on;
require valid_user;
}
server {
error_log /opt/nginx/log/debug.log debug;
listen 8243;
server_name myhost;
more_clear_input_headers 'X-Forwarded-For';
auth_ldap "Forbidden";
auth_ldap_servers my_ldap_server;
if ($request_method !~ ^(GET|OPTIONS|POST)$ ) {
return 403;
break;
}
location ~ ^(/monitor(.*)) {
if ($arg_appli = "") {
return 403;
break;}
rewrite ^/monitor.* /$arg_appli?;
proxy_set_header Host myhost:myport;
root html;
index index.html;
break;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}}
My appli.conf contains:
appli=1 ESB_SUPERADMIN;
The problem is that I always get default_groupe instead of ESB_SUPERADMIN when using this url: http://myhost:myport/monitor?appli=1.
Is something wrong on my configuration?
Thanks for your help.
I'm trying to set up a simple nginx server to act as a proxy between my front end ui and my back end api. The setup is fairly simple. The UI makes all api requests to /api/endpoint and the proxy server passes the request to the api. The proxy also needs to rewrite the request so that instead of going to http://api.location.net/api/endpoint, it goes to http://api.location.net/endpoint. The UI resides on http://api.location.net. This part isn't working (i get a 500 error) and I'm pretty sure it has to do with how I'm writing my rewrite rule. Here's my nginx config.
daemon off;
error_log off;
worker_processes 2;
worker_rlimit_nofile 100000;
events {
worker_connections 50000;
accept_mutex off;
}
http {
include /etc/nginx/mime.types;
access_log off;
sendfile on;
server {
listen 80 default_server;
server_name localhost _;
location / {
alias /srv/site/;
}
location /api/ {
rewrite ^/api ""; # I think this is the problem
proxy_pass http://api.location.net;
proxy_pass_request_headers on;
proxy_pass_header X-ResponseData;
proxy_redirect off;
}
}
}
Any help would be greatly appreciated, nginx is still fairly new for me and the documentation on nginx rewrite doesn't seem to have what I need.
If I understood you right, this should help
location /api/ {
proxy_pass http://api.location.net/;
proxy_pass_request_headers on;
proxy_pass_header X-ResponseData;
proxy_redirect off;
}
Note the URI part at proxy_pass directive
If the proxy_pass directive is specified with a URI, then when a
request is passed to the server, the part of a normalized request URI
matching the location is replaced by a URI specified in the directive:
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
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;
}
}