Nginx Rewrites
Introduction
URL rewriting is a powerful feature in Nginx that allows you to modify incoming request URLs before they're processed. This enables you to create cleaner, more user-friendly URLs, redirect old URLs to new locations, or modify requests before they reach your application.
In this tutorial, we'll explore Nginx's rewrite capabilities in depth, covering:
- How rewriting works in Nginx
- The rewritedirective syntax and flags
- Common use cases and patterns
- Performance considerations
Understanding URL Rewriting
URL rewriting allows a web server to map one URL to another, changing what the server sees without affecting what the client typed in the browser. This creates a layer of abstraction between the URLs users interact with and your actual application structure.
Why Use Rewrites?
- SEO and User-Friendliness: Convert complex URLs with query parameters into clean, readable paths
- Maintenance: Preserve old URLs when restructuring your site
- Security: Hide implementation details and file extensions
- Flexibility: Route requests to different applications or handlers based on patterns
The Nginx Rewrite Directive
The primary tool for URL rewriting in Nginx is the rewrite directive:
rewrite regex replacement [flag];
Let's break down each component:
- regex: A regular expression pattern to match against the request URI
- replacement: The string that will replace the matched URI
- flag (optional): Controls the behavior after the rewrite occurs
Available Flags
- last: Stops processing the current set of rewrite directives and starts a search for a new location match
- break: Stops processing the current set of rewrite directives
- redirect: Returns a temporary redirect (302) with the rewritten URL
- permanent: Returns a permanent redirect (301) with the rewritten URL
Basic Rewrite Examples
Let's start with some simple examples to understand how rewrites work in practice.
Simple URL Rewrite
location /api/ {
    rewrite ^/api/users/([0-9]+)$ /api/v1/users/$1 break;
    proxy_pass http://backend_server;
}
What happens:
- A request to /api/users/123
- Gets internally rewritten to /api/v1/users/123
- The request is then processed according to the location block rules
Redirecting Old URLs to New Ones
server {
    listen 80;
    server_name example.com;
    
    # Redirect old product URLs to new structure
    rewrite ^/products/([0-9]+)$ /shop/item/$1 permanent;
}
What happens:
- A request to example.com/products/42
- Browser receives a 301 (permanent) redirect to example.com/shop/item/42
- The browser automatically navigates to the new URL
Working with Rewrite Conditions
Often, you'll want to apply rewrites conditionally. Nginx provides the if directive for this purpose:
server {
    listen 80;
    server_name example.com;
    
    # Only apply rewrite for mobile devices
    if ($http_user_agent ~* mobile) {
        rewrite ^/(.*)$ /mobile/$1 last;
    }
}
What happens:
- If the user agent contains "mobile"
- A request to /aboutwould be rewritten to/mobile/about
Note: The
ifdirective in Nginx has some limitations and potential issues. It's generally better to uselocationblocks where possible.
Advanced Rewrite Patterns
Let's explore some more complex examples for common use cases.
Creating a Clean URL Structure
server {
    listen 80;
    server_name example.com;
    
    # Rewrite /blog/my-post-title to /blog.php?post=my-post-title
    location /blog/ {
        rewrite ^/blog/(.+)$ /blog.php?post=$1 last;
    }
}
Handling File Extensions Transparently
server {
    listen 80;
    server_name example.com;
    
    # Hide PHP extensions
    location / {
        # Rewrite /page to /page.php
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /$1.php last;
        }
    }
}
Capturing and Using Multiple Path Segments
server {
    listen 80;
    server_name example.com;
    
    # Rewrite /category/subcategory/product-name to /product.php?cat=category&subcat=subcategory&product=product-name
    location / {
        rewrite ^/([^/]+)/([^/]+)/([^/]+)$ /product.php?cat=$1&subcat=$2&product=$3 last;
    }
}
Visualizing Rewrite Flow
Here's a visual representation of how Nginx processes rewrites:
Performance Considerations
Rewrite rules are processed for every request, so it's important to keep them efficient:
- Be Specific: Use location blocks to narrow down where rewrites apply
- Optimize Regular Expressions: Avoid costly backtracking and capture only what you need
- Use try_files When Possible: For simple file existence checks, try_filesis more efficient than rewrites
- Consider Caching: For frequently accessed URLs, consider using proxy caching
Common Use Cases
Let's explore some real-world applications of Nginx rewrites:
Single Page Application (SPA) Support
server {
    listen 80;
    server_name app.example.com;
    root /var/www/spa;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
}
This configuration ensures that all routes in a SPA are properly handled by redirecting non-existent paths back to the main index.html file.
WordPress Pretty URLs
server {
    listen 80;
    server_name blog.example.com;
    root /var/www/wordpress;
    
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
}
This setup allows WordPress to handle pretty permalinks by forwarding requests to index.php when the requested file doesn't exist.
API Version Routing
server {
    listen 80;
    server_name api.example.com;
    
    # Default to latest API version
    location /api/ {
        rewrite ^/api/(.*)$ /api/v2/$1 last;
    }
    
    # Handle specific API versions
    location ~ ^/api/v[0-9]+/ {
        proxy_pass http://backend_servers;
    }
}
Debugging Rewrite Rules
When your rewrite rules aren't working as expected, Nginx provides debugging tools:
- Enable Rewrite Logging:
server {
    # ... other configuration
    
    # Enable rewrite logging
    rewrite_log on;
    error_log /var/log/nginx/rewrite.log notice;
}
- Test with curl:
curl -I http://example.com/test/path
The -I flag shows only the headers, which is useful for checking redirect status codes.
Summary
Nginx rewrites are a powerful tool for manipulating URLs and controlling how requests are processed. We've covered:
- The basic syntax and operation of the rewritedirective
- How to use different flags to control rewrite behavior
- Conditional rewrites using the ifdirective
- Common patterns and real-world examples
- Performance considerations and debugging techniques
With these skills, you can create clean, user-friendly URLs while maintaining flexibility in your application's structure.
Additional Resources
To deepen your understanding of Nginx rewrites:
- The official Nginx documentation on rewrite module
- Learn more about regular expressions for more powerful matching patterns
- Explore the try_filesdirective as a complement to rewrites
Practice Exercises
- Create a rewrite rule that maps /articles/YYYY/MM/titleto/article.php?year=YYYY&month=MM&title=title
- Implement a rule that redirects HTTP requests to HTTPS with a permanent redirect
- Set up a rule that handles both /product/123and/product/123.htmlto the same backend resource
💡 Found a typo or mistake? Click "Edit this page" to suggest a correction. Your feedback is greatly appreciated!