📚 Learning Objectives
By the end of this module, you will:
- Understand URL rewriting vs redirects
- Use rewrite directive
- Configure permanent and temporary redirects
- Handle URL patterns with regex
- Set up clean URLs
- Understand rewrite flags
🔄 Rewrite vs Redirect
Rewrite
- Internal: Changes URL internally, browser doesn't see change
- Same Request: Client makes one request
- Use Case: Clean URLs, routing
Redirect
- External: Browser makes new request to new URL
- Two Requests: Client makes two requests
- Use Case: Moving pages, forcing HTTPS, www/non-www
✏️ Rewrite Directive
Basic Syntax
rewrite regex replacement [flag];
Examples
# Rewrite /old to /new (internal)
rewrite ^/old$ /new last;
# Rewrite with regex
rewrite ^/users/(.*)$ /profile.php?user=$1 last;
🚩 Rewrite Flags
last
Stops processing and searches for new location matching rewritten URI:
location / {
rewrite ^/old$ /new last;
# If /new matches another location, that location is used
}
location /new {
# This location will handle the rewritten /new
}
break
Stops processing rewrite directives but continues in current location:
location / {
rewrite ^/old$ /new break;
# Processing stops here, no more rewrites
# Continues with current location block
}
redirect
Temporary redirect (HTTP 302):
rewrite ^/old$ /new redirect;
permanent
Permanent redirect (HTTP 301):
rewrite ^/old$ /new permanent;
🔀 Common Redirect Patterns
HTTP to HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
Or using rewrite:
server {
listen 80;
server_name example.com;
rewrite ^(.*)$ https://$server_name$1 permanent;
}
www to non-www
server {
listen 80;
server_name www.example.com;
return 301 http://example.com$request_uri;
}
server {
listen 80;
server_name example.com;
# ... main configuration
}
non-www to www
server {
listen 80;
server_name example.com;
return 301 http://www.example.com$request_uri;
}
server {
listen 80;
server_name www.example.com;
# ... main configuration
}
Trailing Slash
# Remove trailing slash
rewrite ^/(.*)/$ /$1 permanent;
# Add trailing slash
rewrite ^/(.*[^/])$ /$1/ permanent;
Force Trailing Slash for Directories
location / {
# Add trailing slash if missing and is directory
rewrite ^([^.]*[^/])$ $1/ permanent;
}
🎯 URL Rewriting Examples
Clean URLs (Remove .php extension)
location / {
# Remove .php extension
rewrite ^/(.*)\.php$ /$1 permanent;
# Add .php extension internally
rewrite ^/(.*)$ /$1.php last;
}
RESTful API Routing
location /api/ {
rewrite ^/api/users/(.*)$ /api/user.php?id=$1 last;
rewrite ^/api/posts/(.*)$ /api/post.php?id=$1 last;
rewrite ^/api/categories/(.*)$ /api/category.php?slug=$1 last;
}
Query String to Path
# Convert /page.php?id=123 to /page/123
location / {
rewrite ^/page/(.*)$ /page.php?id=$1 last;
}
Remove Query Strings
location / {
# Remove query string
rewrite ^(.*)\?.*$ $1 permanent;
}
Add Query Parameters
location / {
rewrite ^(.*)$ $1?source=nginx permanent;
}
📋 Complete Rewrite Examples
Example 1: Clean URLs for PHP Application
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.php index.html;
location / {
# Try files first, then try with .php, then 404
try_files $uri $uri/ @php;
}
location @php {
# Add .php extension
rewrite ^/(.*)$ /$1.php last;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Example 2: Multiple Redirects
server {
listen 80;
server_name example.com www.example.com;
# Redirect www to non-www
if ($host = www.example.com) {
return 301 http://example.com$request_uri;
}
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Example 3: Complex URL Rewriting
server {
listen 80;
server_name example.com;
root /var/www/html;
# Old blog structure to new
rewrite ^/blog/(\d{4})/(\d{2})/(.*)$ /posts/$3 permanent;
# Product pages
rewrite ^/product/(.*)$ /product.php?slug=$1 last;
# User profiles
rewrite ^/user/(.*)$ /profile.php?username=$1 last;
# Category pages
rewrite ^/category/(.*)$ /category.php?cat=$1 last;
location / {
try_files $uri $uri/ =404;
}
}
🔍 Conditional Rewrites
Using if Directive
# Redirect based on condition
if ($request_method = POST) {
return 405;
}
# Redirect old domain
if ($host = olddomain.com) {
return 301 http://newdomain.com$request_uri;
}
# Redirect based on user agent
if ($http_user_agent ~* "bot") {
return 403;
}
Warning: Use if directive carefully. It can cause unexpected behavior.
Better Approach: Map Directive
# Define map
map $host $new_host {
default $host;
olddomain.com newdomain.com;
www.olddomain.com www.newdomain.com;
}
server {
listen 80;
server_name example.com;
if ($new_host != $host) {
return 301 http://$new_host$request_uri;
}
# ... rest of config
}
📝 Practical Examples
Example 1: WordPress Clean URLs
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Example 2: Multiple Domain Redirects
# Redirect multiple old domains to new domain
server {
listen 80;
server_name old1.com old2.com old3.com;
return 301 https://newdomain.com$request_uri;
}
server {
listen 443 ssl http2;
server_name newdomain.com;
# ... main configuration
}
Example 3: API Versioning
location /api/ {
# Rewrite v1 to v2
rewrite ^/api/v1/(.*)$ /api/v2/$1 permanent;
# Current API version
rewrite ^/api/v2/(.*)$ /api/current/$1 last;
}
🧪 Testing Rewrites
Test Configuration
# Test syntax
sudo nginx -t
# Show effective configuration
sudo nginx -T | grep -A 5 rewrite
Test Rewrites
# Test redirect
curl -I http://example.com/old
# Should return 301 or 302
# Test rewrite (internal)
curl http://example.com/old
# Should show content from /new
# Follow redirects
curl -L http://example.com/old
🔒 Security Considerations
Prevent Directory Traversal
# Block attempts to access parent directories
if ($request_uri ~ "\.\./") {
return 403;
}
Block Specific Paths
# Block access to admin
location /admin {
deny all;
return 403;
}
# Block .htaccess and config files
location ~ /\.(ht|git) {
deny all;
return 404;
}
📝 Exercises
- Set up HTTP to HTTPS redirect
- Configure www to non-www redirect
- Create clean URLs by removing file extensions
- Rewrite query strings to path parameters
- Set up multiple domain redirects
- Create RESTful URL routing
- Test your rewrites and redirects
- Implement conditional redirects
✅ Checklist
- [ ] Understand difference between rewrite and redirect
- [ ] Can use rewrite directive
- [ ] Understand rewrite flags (last, break, redirect, permanent)
- [ ] Can set up HTTP to HTTPS redirect
- [ ] Can configure www/non-www redirects
- [ ] Can create clean URLs
- [ ] Understand conditional rewrites
- [ ] Can test rewrites and redirects
➡️ Next Steps
Proceed to Module 5: Caching to learn about caching strategies with NGINX.