nginx rewrite file name on secure connection - http

How can I rewrite the file name on https in nginx configuration?
for example I have
/public/abc.html
/public/abc-s.html
but I want user who access https://mydomain/abc.html load abc-s.html, while http://mydomain/abc-s.html load abc.html.
thx

This can be done by a series of regular expressions; example:
set $hasdashs u; # if we don't match .html we don't want to do a rewrite
if ($uri ~* "^(.*)\.html$") { # are we looking at a .html page? If so, get the base name
set $hasdashs n;
set $shorturi "$1";
}
if ($uri ~ "^(.*)-s\.html$") { # are we looking at a secure page? Get the base name without -s
set $hasdashs y;
set $shorturi "$1";
}
set $schemecheck "$scheme$hasdashs";
if ($schemecheck = "httpy") { #we're using http and looking at a secure page
rewrite . "${shorturi}.html" redirect;
}
if ($schemecheck = "httpsn") { #we're using https and looking at an insecure page
rewrite . "${shorturi}-s.html" redirect;
}
Note that this has to be in the server block and not the location block of the configuration. Tested on NGINX 1.2.1.

Related

Is possible redirect by microservice?

Can I set a variable with an URL returned by a proxy? ... I want to avoid to run Java, PHP, Python etc. Need somethong simple and faster.
Note, to answer comments: "... an URL returned by a proxy" = a microservice that is a black-box returning the URL. Any URL, can be aleatory or function of inputs (passed to the proxy).
If it is possible, how to?
This is fine on my NGINX server, it is returning a string with the necessary URL.
location /_test {
rewrite ^/_test/(.*) /$1 break;
proxy_pass http://127.0.0.1:3000;
}
(here $1 is the input and 127.0.0.1:3000 the black-box microservice)
... How to redirect as return 301 $theNewUrl? Imagining something (illustrative and wrong of course) as
location /_test {
rewrite ^/_test/(.*) /$1 break;
set theNewUrl = proxy_pass(http://127.0.0.1:3000/$1);
return 301 $theNewUrl;
}
To redirect base on path on Ningx, try this:
example.com is your base domain.
server {
server_name myDomain;
location /_test/hello/ {
proxy_pass http://google.com/;
}
location /_test/bye/ {
proxy_pass http://stackoverflow.com/;
}
}
Example:
HTTP request to http://myDomain/_test/hello/$1 will be translated to: http://google.com/$1 you can use it with ports or whatever you want.

nginx server: how to remove first directory from URL

Can anybody please help me to remove first directory name from URL?
My Image location is _data/hotel/3/15377/hotel_image.jpg
But Image path gets changed due to relative URL in code and it become to something like this.
example.com/france/_data/hotel/3/15377/hotel_image.jpg
example.com/usa/_data/hotel/3/15377/hotel_image.jpg
example.com/india/_data/hotel/3/15377/hotel_image.jpg
is their any possibilities to remove dynamic country name from above URL
If you want to rewrite only this particular URL, you can use this location block in your config:
location ~ /[a-z]+/_data/hotel/3/15377/hotel_image.jpg {
try_files /_data/hotel/3/15377/hotel_image.jpg;
}
If you want to rewrite all URLs which lead to /<country>/_data/..., you can use:
location ~ /[a-z]+/_data/(.+) {
try_files /_data/$1;
}
or for stricter URL checking:
location ~ /(?:france|usa|india)/_data/(.+) {
try_files /_data/$1;
}
#Ivan Shatsky's answer is great for files but also if we want to redirect a general url is better if you use the rewrite directive.
Depending where you define the rewrite directive you have two ways to implement it:
A. In the server context
server {
...
rewrite ^/[a-z]+/_data/(.+)$ /_data/$1 last;
...
}
B. In the location context
location ~ /[a-z]+/_data/(.+) {
rewrite ^/[a-z]+/_data/(.+)$ /_data/$1 break;
proxy_pass http://backend;
}
Teo, why did you change the flag to break?* Because, if this directive is put inside of a location context, the last flag might make nginx to run 10 cycles and return the 500 error.
Note:
Remember not add / at the end of the proxy_pass directive. This example wont work:
...
proxy_pass http://backend/;
...

nginx rewrite rule with query parameter

My URL looks like:
localhost/video-detail?videoID=T0r-uCXvDzQ
I want to serve a page with name: T0r-uCXvDzQ.html (videoID.html) which is present in server's file system.
I am trying to write the rewrite rule as follows:-
location / {
rewrite ^/video-detail?videoID=(.*) /$1.html;
}
Also tried:
location / {
rewrite ^/video-detail?videoID=(.*) /$arg_videoID.html;
}
But they are giving 404 error.
How can I use the query parameters in the output rewrite rule.
The following worked for me:-
if ($args ~* "videoID=(.*)") {
set $key1 $1;
rewrite ^(/video-detail)$ /$key1.html;
}

nginx - response based on the requested header

I have nginx 1.0.8 installed.
here is my problem:
I have 2 files : file1.js and file2.js. the requested path is something like this:
www.mysite.com/files_dir/%user%/file.js
If the requested header : "X-Header" exists and has the value "OK" then the responded content should be file1.js else file2.js.
The files are situated in "html/files_dir" and %user% is a set of directories that represents the usernames registered through my service.
How do I configure this in nginx? I'm not interested in php, asp or similar technologies only if it's possible with nginx.
Thanks
map lets you define a variable's value based on another variable. map should be declared at http level (i.e. outside of server):
map $http_x_header $file_suffix {
default "2";
OK "1";
};
Then the following location should do the trick using your new variable $file_suffix
location ~ ^(/files_dir/.+)\.js$ {
root html;
try_files $1$file_suffix.js =404;
}
You could do this with nginx very easily. This is example:
location /files_dir/ {
set $file = file2.js;
if ( $http_x_header = OK ) {
set $file = file1.js;
}
rewrite ^(/files_dir/.*)/file.js$ $1/$file last;
}
You could read about HTTP variables in NGINX here , and about nginx rewrite module here

Complex nginx rewrite rules for subdomains

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/

Resources