I have a problem i want to detect the domain and the device and forward the response to the desktop, www server section of nginx. With a rewrite this is done but the problem is the url, is cleared and substitute with my url, the configuration is the following :
server {
listen 80 default_server;
#this detects any domain
server_name ~^(www\.)?(?<domain>.+)$;
root /home/someone/main;
index index.html index.htm;
set $mobile_rewrite do_not_perform;
# this regex string is actually much longer to match more mobile devices
if ($http_user_agent ~* '(iPhone|iPod|iPad|Android|BlackBerry|webOS|Windows Phone)') {
set $mobile_rewrite perform;
}
location / {
if ($mobile_rewrite = perform) {
rewrite ^ http://m.someone.domain.com$request_uri? redirect;
break;
}
}
}
I tried a different approach with an alias to the path in so of the m.someone.domain.com code section but this doesn't work inside the if witch is inside the location.
You can try modifying your if block in following way.
location / {
if ($mobile_rewrite = perform) {
return 301 http://m.someone.domain.com$request_uri;
}
}
As you are using rewrite rule as redirect so above may work. Also rewrites are heavier.
location / {
if ($mobile_rewrite = perform) {
rewrite ^http://m.someone.domain.com$request_uri? / permanent;
}
}
Try this it might work for u
Related
I have two servicesr accessible via NginX. The web server configuration looks like this:
location /service1/ {
# process php files
}
location /service2/ {
proxy_pass http://127.0.0.1:9999/;
}
However, if one clicks on https://example.com/service1 (or 2) he gets a 404 error. There is no folder called "service1" (or 2) in the website root.
I would like links to "https://example.com/service1" to point to "https://example.com/service1/" (with trailing slash), possibly without specyfing a redirect for every service I have, i.e
location = /service1 {
return 301 https://$host/service1/;
}
location /service1/ {
# process php files
}
location = /service2 {
return 301 https://$host/service2/;
}
location /service2/ {
proxy_pass http://127.0.0.1:9999/;
}
I have already tried try_files $uri $uri/ =404;, but it seems to only work for real files and folders in the website root, no "virtual" subdirectories.
I am avoiding configurations like location /service { ... } because they seem more vulnerable.
Inside your location = blocks you need to generate an internal redirect to $uri/. You can achieve this using try_files or rewrite...last.
For example:
location = /service1 {
try_files nonexistent $uri/$is_args$args;
}
Notice that the internal redirection must be the last parameter. See this document for details.
Or:
location = /service1 {
rewrite ^(.*)$ $1/ last;
}
See this document for details.
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 want to set different URLs for desktop and mobile
I already tried this code in nginx.conf file
http {
server {
listen 80;
server_name 1.2.3.4;
set $mobile_request false;
if ($http_user_agent ~* '(Mobile|WebOS)') {
set $mobile_request true;
}
if ($mobile_request = true) {
rewrite ^ /high-mobile/html; #path of my mobile html files
break;
}
if ($mobile_request = false) {
rewrite ^ /high/html; #path of my desktop html files
break;
}
location / {
root /home/ubuntuvm/; #root url
index index.html index.htm; #default home page
}
This is my code when i hit the url in browser it gave error like
redirected you too many times
Failed to load resource: net::ERR_TOO_MANY_REDIRECTS
http://1.2.3.4/high-mobile/html/#/:1 GET http://1.2.3.4/high-mobile/html/ net::ERR_TOO_MANY_REDIRECTS
Thankyou in advance.....
I got the solution
location = /high/ {
if ($mobile_request = true) {
return 301 $scheme://ip_addr/high-mobile/html/index.html#/;
}
Here is my attempt at a solution.
http {
server {
listen 80;
server_name 1.2.3.4;
set $mobile_request false;
#If it's a mobile user-agent, set it to true.
if ($http_user_agent ~* '(Mobile|WebOS)') {
set $mobile_request true;
}
#If it's not a request to a mobile site, append "desktop" to the "mobile_request" variable.
if ($request_uri !~ "^.*/high-mobile/.*$"){
set $mobile_request "${mobile_request}+desktop";
}
#If it is a mobile user-agent AND it is a request to the desktop site, redirect to the mobile site.
if ($mobile_request = "true+mobile") {
#Clear the variable of any data, so that it doesn't induce a redirect loop with old data for new requests.
set $mobile_request "";
rewrite ^ /high-mobile/html; #path of my mobile html files
break;
}
location / {
root /home/ubuntuvm/; #root url
index index.html index.htm; #default home page
}
}
}
The assumption made in the solution:
All requests are by default to the desktop site and /high/ is in the URI, thus there is no need to check the negation of $mobile_request.
If this is not the case, you'll need to post your full NGINX configuration as well as the directory structure you're using. Any config more complicated than this is generally wrong unless you're trying to do something very specific or you're supporting a legacy infrastructure. I hope this helps.
I'm using Nginx 1.6.2. I read that if () is evil and it's not good using it so I need a bit help, because I can't do what I want without using if(). I will post the rules I have with if and would ask if somebody could help me and tell me how to not use if () and use something else and get the same result.
# REDIRECT NON-WWW TO WWW.
if ($http_host != "www.site.eu") {
rewrite ^ http://www.site.eu$request_uri permanent;
}
# REMOVE INDEX FILES FROM URL FOR SEO PURPOSE.
if ($request_uri ~ "/index.php") {
rewrite ^ /$1 permanent;
}
# REMOVE ANY MULTIPLE SLASHES IN THE URL.
if ($request_uri ~* "\/\/") {
rewrite ^/(.*) $scheme://$host/$1 permanent;
}
First rule should be replaced with separate server blocks
server {
listen 80 default_server;
return 301 http://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
# normal config
}
Other ifs usually are not necessary. Just don't generate links with index.php and you will not need to strip it.
In the official wiki introduction it says that there are some cases which are ok. Have a look at this quote:
The only 100% safe things which may be done inside if in location
context are:
return ...; rewrite ... last;
At the end of the introduction there is an example which also features a rewrite command. So your code looks ok, too.
EDIT: You should also have a look at how the if works.
You can replace this block
# REMOVE INDEX FILES FROM URL FOR SEO PURPOSE.
if ($request_uri ~ "/index.php") {
rewrite ^ /$1 permanent;
}
with this
location ~ ^/index.php/(.*[^/])$ { return 301 $scheme://$host/$1/$is_args$args; }
location ~ ^/index.php/(.*)/$ { return 301 $scheme://$host/$1/$is_args$args; }
I also don't think you need to worry about the last rule for double // because nginx by default automatically takes care of that before it even gets to the point of matching location blocks
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/