I want to have an nginx rule that will proxy requests with empty path / to a back end server, and another rule that match non empty paths, ex. http://mysite/x/y/z
The following two rules do not do this, the second one is catching all:
# empty path
location ^/?$ {
proxy_pass http://127.0.0.1:8000;
}
location / {
expires -1;
alias /var/static-site/;
}
I have tried /.*/ for the second rule, without success...
Use the "=" modifier to process an exact match on "/":
location = / {
proxy_pass http://127.0.0.1:8000;
}
location / {
expires -1;
alias /var/static-site/;
}
Related
I would like to rewrite legacy links using a query parameter type of URL to a new style of URL.
Ex.
example.com/page?id=1 -> example.com/page/1
example.com/otherpage?id=1 -> example.com/otherpage/1
Currently I have the following configuration using the evil if.
if ($args ~* "id=(.*)") {
set $w1 $1;
rewrite .* $scheme://$host/page/$w1? permanent;
}
Note: I am using CloudFront, and relying on the host header above.
If the above is in a server block, with no other location block - would this qualify as a non-evil use of if in NGINX config? Also, the above only supported /page/. Any better ideas for making that portion work for otherpage and other pages?
I have seen a few other ideas discussing using a map, but I'm not quite sure how to bring it all together? I was thinking something along the lines of:
map $args_id ?? {
default ?
??
}
...
server {
...
???
}
UPDATE:
Based on the Answer from #Ivan, this was my final solution:
server {
listen 80;
root /usr/share/nginx/html;
index index.html index.htm;
# Handle legacy requests
if ($args ~* "id=(.*)") {
set $w1 $1;
rewrite ^ $scheme://$host$uri/$w1? permanent;
}
}
Your if construction isn't evil. You can use something like
rewrite ^ $scheme://$host$uri/$w1? permanent;
for any page. More complex example if you want to process both example.com/page?id=1 and example.com/page/?id=1:
map $uri $maybe_slash {
~/$ "";
default "/";
}
...
server {
...
rewrite ^ $scheme://$host$uri$maybe_slash$w1? permanent;
...
}
I have been struggling with setting up Nginx for our use case.
When I set up Nginx with the following config:
location /dep-core {
proxy_pass http://node-server:7070/;
}
and call the server with following endpoint:
<END-POINT>/dep-core/api/login
the call is redirected to
<ADDRESS-AFTER-RESOLUTION>//api/login
with two leading //s.
and when I remove the trailing / in proxy_pass after 7070:
location /dep-core {
proxy_pass http://node-server:7070;
}
the call is redirected to
<ADDRESS-AFTER-RESOLUTION>/dep-core/api/login
with leading /dep-core appended.
I want my call to redirect my call to:
<ADDRESS-AFTER-RESOLUTION>/api/login
What would be the standard way to achieve this??
For correct translation from /dep-core/foo to /foo, the location directive requires a trailing /.
For example:
location /dep-core/ {
proxy_pass http://node-server:7070/;
}
See this document for details.
To translate /dep-core to /, you can use a rewrite...break with a clever regular expression in the second block of your question. But a simple solution is to add an exact match location for that single edge case.
For example:
location = /dep-core {
rewrite ^ $uri/ last;
}
location /dep-core/ {
proxy_pass http://node-server:7070/;
}
We have following config:
location / {
#This statement adding extra slash to url
if ($http_cookie !~ 'skip_geo=yes') {
set $allow_visit "${allow_visit}_at_all";
}
if ($allow_visit = no_at_all) {
rewrite ^ http://domain/block.html;
}
proxy_pass http://backend/;
}
Why extra slash is added?
Config can be fixed by removing slash from proxy_pass, but whole story looks unstable.
My question is about nginx "location" configuration blocks:
If I want to make a location with a space character (well, %20) in the URL I can do it like so:
location ^~ "/Style Library/" {
}
If I want to make a case-insensitive location, I can do it like so:
location ~* ^/StyleLibrary/ {
}
However, I can't find a way of getting case-insensitive locations with space characters working. None of these appear to work:
location ~* "^/Style Library/" {
}
location ~* ^/Style[^_]Library/ {
}
location ~* ^/Style\sLibrary/ {
}
location ~* ^/Style.Library/ {
}
Can anyone help?
Do you have other regex locations that may be handling the request earlier in the server block? I just ran a test locally and was able to make the following location work:
location ~* "^/Style Library/" {
rewrite ^ /dump.php;
}
where /dump.php is just a simple script that does a var_export($_SERVER);
I tested this with
curl -i "dev/StYlE LiBrArY/"
I'd guess that some other location is handling the request instead of that regex location.
I currently have the following (hacky) re-write rule in my nginx.conf to allow dynamic sub-domains to be re-directed to one Django instance.
set $subdomain "";
set $subdomain_root "";
set $doit "";
if ($host ~* "^(.+)\.domain\.com$") {
set $subdomain $1;
set $subdomain_root "/profile/$subdomain";
set $doit TR;
}
if (!-f $request_filename) {
set $doit "${doit}UE";
}
if ($doit = TRUE) {
rewrite ^(.*)$ $subdomain_root$1;
break;
}
I'm sure there is a more efficient way to do this but I need to change this rule so that any requests to *.domain.com/media/* or *.domain.com/downloads/* go to domain.com/media/* and domain.com/downloads/*.
You can use regular expression server names (see http://nginx.org/en/docs/http/server_names.html#regex_names) and assign a matching group to a variable $subdomain directly:
server {
listen 80;
listen 443;
server_name ~^(?<subdomain>.+)\.domain\.com$
location / {
rewrite ^ /profile/$subdomain$request_uri;
}
}
Actually I think it is much easier to change the nginx re-write rules than to write middleware for django to do this. After reading up on how nginx processes it's location matching (most exact -> least exact) I created locations for /media and /download as well as a catch all location for / I then moved the rewrite rule to under the / location and simplified it - as I'm no longer worried about checking for files because this entire location is passed to django - the rule becomes :
set $subdomain "";
set $subdomain_root "";
if ($host ~* "^(.+)\.domain\.com$") {
set $subdomain $1;
set $subdomain_root "/profile/$subdomain";
rewrite ^(.*)$ $subdomain_root$1;
break;
}
and would probably be even simpler if my nginx\regex scripting was better :)
Perhaps a better idea would be to configure django to handle subdomains instead of adding a rewrite in your webserver. Here's how I did it: http://sharjeel.2scomplement.com/2008/07/24/django-subdomains/