Professional Documents
Culture Documents
Table of Contents
1. Introduction .....................................................................................................................................1
2. Nginx HTTP rewrite functionality....................................................................................................1
3. Rewrite examples.............................................................................................................................7
4. Rewrite rule best practices..............................................................................................................11
5. Apache rules to Nginx rules conversion.........................................................................................12
7. Dependencies..................................................................................................................................15
8. References......................................................................................................................................15
1. Introduction
More often than not there are times when your initial thought process changes mid way through
your production ready application and you decide to change your application url. It could be your
scheme (from a non-www to a www or vice-versa) or it could be your protocol (say, from http to
https) or it could be the pages moved from one directory to another directory or even the change of
domain name or even at times it is required to perorm a URL rewrite in order to map a nonexisting /foo context to the actual /bar one. For example :
UC 1 (non-WWW to WWW conversion) :
http://site.com/some-page-title.html to go to www.site.com/some-page-title.html
UC 2 (http to https conversion):
http://test.com to go to https://test.com
UC 3 :
http://www.example.com/products/1234 to go to http://www.example.com/show?product= 1234
UC 4:
http://example.com/issue1 --> http://example.com/shop/issues/custom_issue_name1
http://example.com/issue2 --> http://example.com/shop/issues/custom_issue_name2
http://example.com/issue3 --> http://example.com/shop/issues/custom_issue_name3
UC 5:
http://www.abc.com to go to "http://partner.abc.com/xyz"
UC 6:
Perform the URL rewrite based on the headers in the request. For Example suppose a request
www.abc.com with Accept-Language header as German (ge) is received, ane this the URL needs
to be rewritten to www.abc.com/ge in order to serve a German web page instead of the default
English page
2. Nginx HTTP rewrite functionality
The URL Rewriting and Redirection functionality of Nginx is being provided by the HttpRewrite
module. This module makes it possible to change URI using regular expressions (PCRE), and to
redirect and select configuration depending on variables. NGINX's rewrite module is a simple
regular expression matcher combined with a virtual stack machine.
4. redirect - returns a temporary redirect with the 302 code. It means that a page has moved
temporarily to a new location. It is used if a replacement string does not start with http://
or https://. This code is not recommended for domain change.
Let us understand the differnece between last and break
location /video_test {
rewrite ^/video_test /video/ break;
}
In the above configuration since we have used the break flag with rewrite, it stops the rewrite
there and tries to find an upstream server with the changed URI in that section. As we don't have
one an 404 error message is returned to the client. The correct syntax would be to use last, if we
want Nginx to find the correct upstream withe the changed URI or use return or we can specify
where the request to be redirected to in that location section.
The permanent flag redirect URL with http status code 301. It means that a page has permanently
moved to a new location. This code is recommended by search engine giant Google:
The 301 redirects are particularly useful in the following circumstances:
1. You've moved your site to a new domain, and you want to make the transition as seamless as
possible.
2. People access your site through several different URLs. If, for example, your home page can
be reached in multiple ways - for instance, http://example.com/home,
http://home.example.com, or http://www.example.com - it's a good idea to pick one of those
URLs as your preferred (canonical) destination, and use 301 redirects to send traffic from
the other URLs to your preferred URL. You can also use Webmaster Tools to set your
preferred domain.
3. You're merging two websites and want to make sure that links to outdated URLs are
redirected to the correct pages.
There exists another directive known as return which stops the processing and return the
specified code to the client.
Syntax: return code [text];
return code URL;
return URL;
context: server, location, if
The return directive may indicate a status code, a status code with some text, or a status code with a
URI. If a bare URI is the sole parameter, then the status code is understood to be a 302. When the
text is placed after the status code, that text becomes the body of the response. If a URI is used
instead, then that URI becomes the value of the location header, to which the client will then be
redirected.
As a special case, a redirect URL can be specified as a URI local to this server, in which case the
full redirect URL is formed according to the request scheme ($scheme) and the
server_name_in_redirect and port_in_redirect directives. In addition, a URL for temporary
redirect with the code 302 can be specified as the sole parameter. Such a parameter should start with
the http://, https://, or $scheme string. A URL can contain variables.
When you use http:// or https:// with rewrite or use return then client gets the response and
tries to the new URL in this case the changed URL will become visible on the client browser. When
rewrite modifies the URL and forwards the request to the client then client will not see the changed
URL on its browser.
The comparison between rewrite and return rewrite
Example:
rewrite ^ https://$server_name$request_uri?
permanent;
return
Example:
return 301 https://
$server_name$request_uri;
If a replacement string includes the new request arguments, the previous request arguments are
appended after them. If this is undesired, putting a question mark at the end of a replacement string
avoids having them appended, for example :
rewrite ^/users/(.*)$ /show?user=$1 last;
The above command will map http://www.example.com/users/1234/abcxyz to
http://www.example.com/show?user=1234/abcxyz
whereas
rewrite ^/users/(.*)$ /show?user=$1? last;
the above command will map http://www.example.com/users/1234/abcxyz to
http://www.example.com/show?user=1234
Let us look at more directive called if directive
Syntax: if (condition) { . . . }
Default:
Context: server, location
The if directive evaluates the specified condition. If true, the directives of this module specified
inside the braces are executed, and a request is assigned the configuration inside the if directive.
Configurations inside the if directives are inherited from the previous configuration level.
The condition may be any of the following:
}
if ( $slow ) {
limit_rate 10 k ;
}
if ( $ invalid_ referer ) {
return 403;
}
3. Rewrite examples
Example 1: www to non-www redirect
For new websites, having the www before your domain is really not needed. Here is how to redirect
the www version of your website to the cleaner, non-www version.
server {
server_name www.domain.com;
return 301 $scheme://domain.com$request_uri;
}
server {
server_name domain.com;
......
}
Example 2: non-www to www redirect
Irule syntax
when HTTP_REQUEST {
if { [HTTP::host] eq "domain.com" } {
HTTP::redirect
http://www.domain.com[HTTP::uri]
}
}
location ~ /[0-9]+ {
rewrite "/([0-9]+)" /v.php?id=$1? last;
}
(ii)
http://example.com/issue1 --> http://example.com/shop/issues/custom_issue_name1
http://example.com/issue2 --> http://example.com/shop/issues/custom_issue_name2
http://example.com/issue3 --> http://example.com/shop/issues/custom_issue_name3
location /issue {
rewrite ^/issue(.*) /shop/issues/ustom_issue_name$1 last;
}
If you want to the return the changed URI instead of forwarding, do this :
location /issue {
rewrite ^/issue(.*) http://$server_name/shop/issues/custom_issue_name$1 permanent;
}
Irule syntax
location /bus {
rewrite ^/bus(.*) /greyhound/searchBus.do?
stationName=$1? last;
}
when HTTP_REQUEST {
set uri [HTTP::uri]
switch -glob [string tolower [HTTP::uri] ] {
"/bus/*" {
HTTP::uri "/greyhound/searchBus.do?
stationName=[string range $uri 5 end]"
}
}
}
From
To
http://long-domain-name-example.com
http://www.example.com
http://long-domain-name-example.com/file.html http://www.example.com/file.html
http://long-domain-name-example.com/cgihttp://www.example.com/cgi-bin/register.cgi?
bin/register.cgi?action=1file easier to read. This action=1
approach decreases nginx processing requi
http://long-domain-nameexample.com/static/js/lib.js?v=2
http://www.example.com/static/js/lib.js?v=2
server {
listen
75.126.153.206:80;
server_name long-domain-name-example.com ;
root
/usr/local/nginx/html;
index
index.html;
rewrite ^ $scheme://www.example.com $request_uri permanent;
# ....
}
Example 5: Redirect to a different domain with nginx
From:
example.org
example.org/foo.html
example.org/show.php?arg=value
example.org/dir1/dir2/bar.cgi
To:
example.com
example.com/foo.html
example.com/show.php?arg=value
example.com//dir1/dir2/bar.cgi
server {
server_name .example.org;
return 301 $scheme://example.com$request_uri;
}
server {
server_name example.com;Enables or disables logging of ngx_http_rewrite_module module
directives processing results into the error log at the notice level.
# rest of config, if any goes below ...
}
Example 6: Redirecting all the HTTP traffic to HTTPS
HTTP to HTTPS redirect
Nginx syntax
server {
listen *:80;
return 301 https://$host$request_uri ;
}
Irule syntax
when HTTP_REQUEST {
HTTP::respond 301 location "https://
[HTTP::host][HTTP::uri]"
}
The following is the complete configuration of nginx in order to redirect all the HTTP traffic to
HTTPS traffic
upstream backend {
server 127.0.0.1:8080;
}
server {
listen *:80;
return 301 https://$host$request_uri permanent;
}
server {
listen *:443;
ssl on;
ssl_protocols SSLv3 TLSv1;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/cert.key;
location / {
proxy_pass http://backend;
}
}
P.S. Make sure you have the certificates cd /etc/nginx
mkdir ssl
openssl req -new -x509 -days 9999 -nodes \
-out ssl/cert.pem -keyout ssl/cert.key
chown -R www-data:www-data ssl
chmod -R 700 ssl
If your application needs http to https redirect only for certain uris like for example, sign-in or signup then do the following server {
listen 80;
server_name http://www.example.com;
root /path-to-public-folder-of-project;
passenger_enabled on;
location ~ ^/(sign-up|sign-in) {
return 301 https://$host$request_uri;
}
}
Example 7: Redirecting based on the HTTP user agent
Irule syntax
if ($http_user_agent ~* ^Mozilla) {
rewrite ^/$ /homepage.max.html break;
}
when HTTP_REQUEST {
if { [HTTP::header "User-Agent"] contains
"iPhone"] } {
HTTP::redirect "http://m.mysite.com" }
}
}
}
With if directives Nginx is forced to evaluate every request for all domains. Evaluating every
request against if directives is extremely inefficient. Avoid using if directives and use two server
directives as shown below :
server {
server_name www.domain.com;
return 301 $scheme://domain.com$request_uri;
}
server {
server_name domain.com;
[...]
}
server_name example.com;
rewrite ^ http://www.example.com$request_uri permanent;
}
Rule #4: Replace RewriteCond with if for variable checks
This rule applies only after having applied rules 1 to 3. If there are any remaining conditions not
covered by those rules, then if may be applied to test the values of variables. Any HTTP variable
may be used by prefixing the lowercased name of the variable with $http_. If there are hyphens (-)
in the name, these are translated into underscores (_).
The following example (taken from Apache's documentation on the mod_rewrite module at
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html) is used to decide which page should be
delivered to a client based on the User-Agent header:
RewriteCond %{HTTP_USER_AGENT} ^Mozilla
RewriteRule ^/$ /homepage.max.html
RewriteCond %{HTTP_USER_AGENT} ^Lynx
RewriteRule ^/$ /homepage.min.html [L]
RewriteRule ^/$ /homepage.std.html [L]
This can be translated to an NGINX configuration as follows:
if ($http_user_agent ~* ^Mozilla) {
rewrite ^/$ /homepage.max.html break;
}
if ($http_user_agent ~* ^Lynx) {
rewrite ^/$ /homepage.min.html break;
}
index homepage.std.html;
6. Apache rules to Nginx rules conversion tool
The apache configurations can be converted to the nginx configuration using this tool :
http://winginx.com/htaccess
http://labs.gidix.de/nginx/
7. Dependencies
1. server name in redirect
Syntax: server_name_in_redirect on | off;
Default: off
Context: http, server, location
Enables or disables the use of the primary server name, specified by the server name
directive, in redirects issued by nginx. When disabled, the name from the Host request header field
is used. If this field is not present, an IP address of the server is used.
2. port in redirect
Syntax: port_in_redirect on | off;
Default: on
Context: http, server, location
Enables or disables specifying the port in redirects issued by nginx.
8. References
1. http://wiki.nginx.org/NginxHttpRewriteModule
2. http://wiki.nginx.org/Pitfalls
3. http://wiki.nginx.org/IfIsEvil
4. http://agentzh.blogspot.in/2011/03/how-nginx-location-if-works.html
5.
Note: