Tutorial

Nginx Rewrite URL Rules Examples

Published on August 3, 2022
author

Meghna Gangwar

Nginx Rewrite URL Rules Examples

NGINX rewrite rules are used to change entire or a part of the URL requested by a client. The main motive for changing an URL is to inform the clients that the resources they are looking for have changed its location apart from controlling the flow of executing pages in NGINX. The return and rewrite directives in NGINX are used to rewrite URL. Both the directives perform the same function of rewriting URL. However, the rewrite directive is more powerful than the return directive since complex rewriting that requires parsing of URL can be done with rewrite directive only. In this tutorial, we will explore how both return and rewrite directives are used in NGINX to change or rewrite the URL.

NGINX Return directive

The easiest and cleaner way to rewrite an URL can be done by using the return directive. The return directive must be declared in the server or location context by specifying the URL to be redirected.

1. NGINX Return directive in Server context

The return directive in server context is very useful in a situation where you have migrated your site to a new domain and you want to redirect all old URLs to the new domain. Further, it also helps in canonicalization of URL by forcing your site to redirect to either www or non-www version.

server {
        listen 80;
        server_name www.olddomain.com;
        return 301 $scheme://www.newdomain.com$request_uri;
}

The return directive in the above server context redirect URL destined to site www.olddomain.com to www.newdomain.com. As soon as NGINX receives an URL with www.olddomain.com, it stops processing the page and sends a 301 response code along with rewritten URL to the client. The two variables used in the above return directive are $scheme and $request_uri. The variable $scheme is used to define scheme of the URL (http or https) and the variable $request_uri contains complete URI with parameters if any. Remember both the variable fetches this information from input URL while rewriting the URL.

2. Return directive in Location context

In some situation, you may want to redirect pages instead of redirecting domains. The return directive inside the location block enables you to redirect specific pages to a new location.

location = /tutorial/learning-nginx {
     return 301 $scheme://example.com/nginx/understanding-nginx
}

In the above example, whenever a request URI matches exactly with pattern /tutorial/learning-nginx, NGINX will redirect the same to the new location https://example.com/nginx/understanding-nginx/ You can also redirect everything for a specific path to a new location. The following example shows how to redirect all pages those falls under /tutorial to https://example.com/articles.

location /tutorial {
     return 301 $scheme://example.com/articles
}

NGINX Rewrite directive

We can also use rewrite directive to rewrite URL in NGINX. Like return directive, rewrite directive can also be placed in server context as well as in location context. The rewrite directive can perform complicated distinctions between URLs and fetch elements from the original URL that don’t have corresponding NGINX variables thereby making it more useful than return directive. The syntax of rewrite directive is:

rewrite regex replacement-url [flag];
  • regex: The PCRE based regular expression that will be used to match against incoming request URI.
  • replacement-url: If the regular expression matches against the requested URI then the replacement string is used to change the requested URI.
  • flag: The value of flag decides if any more processing of rewrite directive is needed or not.

Remember, The rewrite directive can return only code 301 or 302. To return other codes, you need to include a return directive explicitly after the rewrite directive

NGINX Rewrite directive examples

Let us quickly check few rewrite rules to get you started with it starting from rewriting a simple html page to another URL:

1. Rewrite static page

Consider a scenario where you want to rewrite an URL for a page say https://example.com/nginx-tutorial to https://example.com/somePage.html. The rewrite directive to do the same is given in the following location block.

server {
          ...
          ...
          location = /nginx-tutorial 
          { 
            rewrite ^/nginx-tutorial?$ /somePage.html break; 
          }
          ...
          ...
}

Explanation:

  • The location directive location = /nginx-tutorial tells us that the location block will only match with an URL containing the exact prefix which is /nginx-tutorial.

  • The NGINX will look for the pattern ^/nginx-tutorial?$ in the requested URL.

  • To define the pattern, the characters ^,? and $ are used and have special meaning.

  • ^ represents the beginning of the string to be matched.

  • $ represents the end of the string to be matched.

  • ? represents non greedy modifier. Non greedy modifier will stop searching for pattern once a match have been found.

  • If the requested URI contains the above pattern then somePage.html will be used as a replacement.

  • Since the rewrite rule ends with a break, the rewriting also stops, but the rewritten request is not passed to another location.

2. Rewrite dynamic page

Now consider a dynamic page https://www.example.com/user.php?id=11 where the dynamic part is id=11(userid). We want the URL to be rewritten to https://exampleshop.com/user/11. If you have 10 users then there is a need of 10 rewrite rules for every users if you follow the last method of rewriting URLs. Instead, It is possible to capture elements of the URL in variables and use them to construct a single rewrite rule that will take care of all the dynamic pages.

server {
          ...
          ...
          location = /user.php 
          { 
            rewrite user.php?id=$1 ^user/([0-9]+)/?$ break; 
          }
          ...
          ...
}

Explanation:

  • The location directive location = /user tells NGINX to match the location block with an URL containing the exact prefix which is /user.
  • The NGINX will look for the pattern ^user/([0-9]+)/?$ in the requested URL.
  • The regular expression within square bracket [0-9]+ contains a range of characters between 0 and 9. The + sign signifies matching one or more of the preceding characters. Without the + sign, the above regular expression will match with only 1 character like 5 or 8 but not with 25 or 44.
  • The parenthesis ( ) in the regular expression refers to the back-reference. The $1 in the replacement URL user.php?id=$1 refers to this back-reference.

For example, if https://www.example.com/user/24 is the input URL then the user id 24 will match with the range in the back-reference resulting in the following substitution: https://www.example.com/user.php?id=24

3. Advance URL Rewriting

Let us proceed with another example where we want the URL https://www.example.com/user.php?user_name=john to be rewritten to https://www.example.com/user/login/john. Unlike previous rewrite rule, The dynamic part of the URL user_name=john now contains range of alphabetic characters. The rewrite rule for this scenario is given below:

server {
          ...
          ...
          location = /user.php 
            { 
                rewrite user.php?user_name=$1 ^user/login/([a-z]+)/?$ break;           
            }
          ...
          ...
  }

Explanation:

  • The location directive location = /user/login/john tells NGINX to match the location block with an URL containing the exact prefix which is /user/login/john.
  • The NGINX will look for the pattern ^user/login/([a-z]+)/?$ in the requested URL.
  • The regular expression within square bracket [a-z]+ contains range of characters between a to z. The + sign signifies matching one or more of the preceding characters. Without + sign, the above regular expression will match with only 1 character like a or c but not with john or doe.
  • The parenthesis ( ) in the regular expression refers to the back-reference. The $1 in the replacement URL user.php?user_name=$1 refers to this back-reference.

For example, if the input URL is https://www.example.com/user/login/john then the user name “john” will match with the range in the back-reference resulting in the following substitution: https://www.example.com/user.php?user\_name=john

4. Rewrite with multiple back reference

In this example, we will also find out how to rewrite an URL by using multiple backreferences. Let us assume the input URL is https://example.com/tutorial/linux/wordpress/file1 and we want to rewrite the URL to https://example.com/tutorial/linux/cms/file1.php. If you closely look at the input URL, it starts with /tutorial, and somewhere later in the path the string wordpress needs to be replaced with string cms. Further, a file extension (php) also needs to be appended at the end of the filename. The rewrite rule for this scenario is given below:

server {
          ...
          ...
          location /tutorial
          {
             rewrite ^(/tutorial/.*)/wordpress/(\w+)\.?.*$ $1/cms/$2.php last;
          }
          ...
          ...
  }

Explanation:

  • The first back reference ^(/tutorial/.*) in the regular expression used to match any input URL starting with /tutorial/foo
  • The second back reference (\w+) is used to capture the file name only without extension.
  • The above two back references are used in the replacement URL using $1 and $2
  • The last keyword instructs NGINX to stop parsing of more rewrite conditions, even on the next location match !

Summary

You can now rewrite URL using either rewrite or return directive. The rewrite examples used in this tutorial are simple and easy to understand. You can now proceed with writing more complex rewrite rules!

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Meghna Gangwar

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
January 16, 2020

Pretty awesome, but you’ve gramatically described what you want things re-written to incorrectly. you want to rewrite an URL for a page say https://example.com/somePage.html to https://example.com/nginx-tutorial You’re doing the exact opposite in your examples. that applies to all of them. Nice page though

- Peter

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    April 8, 2020

    How can we add multiple rewrite rules? I’m trying the build the docker image and after copying the file to /etc/nginx the entries are getting deleted and I can see only one rewrite rule.

    server {
           listen       8080;
           server_name nginx.com;
           access_log      /opt/www/logs/access.log;
           error_log       /opt/www/logs/error.log;
           access_log off;
           underscores_in_headers on;
    
           rewrite ^/services/rest/1.0/account/accountnumber/(.*) https://nginx.com//account/services/account/accountnumber/$1 last;
           rewrite ^/services/rest/1.0/user/email/(.*) https://nginx.com/user/services/user/email/$1 last;
           rewrite ^/services/rest/1.0/user/authenticate?(.*)  https://nginx.com/user/services/user/authenticate?$1 last;
           }
    

    - Yograj Patel

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      June 28, 2020

      Can nginx process multiple rewrite rules for the same request? So we can arrange rules in a hierarchy. # Client calls via version number rewrite /1\.(\d+)/(.*) /oldversion/$1 rewrite/2\.(\d+)/(.*) /newversion/$1 # App1 does not care rewrite /.*/app1DoesNotCare # App2 has 2 versions rewrite/oldversion/app2 /legacyVerApp2 rewrite/newversion/app2 /newVerApp2

      - Marc Cawood

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        July 7, 2020

        As peter said in his comment 6 months ago, these examples are all doing the opposite of what is stated. i.e. Changing B to A, but states how to change A to B… The logic/regex patterns are correct, but it would help to correct the stated intent in each example as I only realised this when working through the logic, but only after doubting myself twice.

        - Steven Weston

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          July 14, 2020

          Can you help me with the configuration for NGINX re-write: Incoming request HTTP://abc.com/a--b--c/ Rewrite URL would be: Http://pqr.com/a/b/syx Incoming request HTTP://abc.com/a--b--d/ Rewrite URL would be: Http://pqr.com/a/b/xyz Notice: I have to use incoming request value c or d and convert it to syx and xyz. Please help with what change I’ll have to make.

          - Vivek Jain

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            July 25, 2020

            Hello, thanks for this great tutorial. I am trying to figure out a redirect pattern that should be probably simple but I can’t make it out from your explanation, so maybe you can help. I need to rewrite many URLs that follow this pattern: https://domainname.com/xxxx/xx/xx/post-title What I am looking to achieve is to strip out the “x” characters in the URL, these are numbers, and redirect to a clean URL that looks so: https://domainname.com/post-title So I understand that I need to both rewrite the URL and also catch the “post-title” which is dynamic and different for each post. Any ideas? Thanks in advance Maurice

            - Maurice

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              August 17, 2020

              Examples 2 and 3 have the regex and the request_url backwards.

              - Kobi

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                September 23, 2020

                where at do you write these rules at nginx? Thanx

                - seriously

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  October 6, 2020

                  Hi trying to return 404 for all requests except for when it has /v2/blah example the following should return 404 www.journaldev.com www.journaldev.com/products www.journaldev.com/products/blah but, the following should return 200 OK www.journaldev.com/v2/blah but, the catch is, I cannot touch the location block location / { … } is that possible to do? Have tried everything I know of,( don’t have much experience with nginx)

                  - Edino

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    January 22, 2021

                    Hi * great tutorial thanks! What if I want to rewrite from https://sub1.domain.com/ to physically https://some-other-domain.com/this/is/important/link.html but the browser should show https://sub1.domain.com/this/is/important/link.html in other words some-other-domain.com needs to be hidden from the public thanks Markus

                    - Markus Kugler

                      Try DigitalOcean for free

                      Click below to sign up and get $200 of credit to try our products over 60 days!

                      Sign up

                      Join the Tech Talk
                      Success! Thank you! Please check your email for further details.

                      Please complete your information!

                      Become a contributor for community

                      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                      DigitalOcean Documentation

                      Full documentation for every DigitalOcean product.

                      Resources for startups and SMBs

                      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                      Get our newsletter

                      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                      New accounts only. By submitting your email you agree to our Privacy Policy

                      The developer cloud

                      Scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Get started for free

                      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                      *This promotional offer applies to new accounts only.