When migrating image storage locations in Nginx, we often need to handle legacy URL patterns while ensuring proper fallback behavior. The specific requirement is:
- Check if requested image exists at original path (/images/...)
- If not found, verify existence at new path (/website_images/...)
- Only redirect when the new path exists, otherwise return 404
For Nginx versions without try_files
support, we can use this configuration:
location ~* ^/images/(.+)\.(png|jpg|jpeg|gif)$ {
# First check if file exists in original location
if (-f $document_root/images/$1.$2) {
break;
}
# Then check new location
if (-f $document_root/website_images/$1.$2) {
rewrite ^/images/(.*)$ /website_images/$1 permanent;
}
# Else will return 404 automatically
}
Since this performs multiple filesystem checks, consider these optimizations:
- Add regex patterns to only match image extensions
- Implement caching if you have many redirects
- Set proper expires headers for redirected assets
For large-scale implementations, Nginx map feature can be more efficient:
map $uri $new_uri {
~^/images/(.*) /website_images/$1;
}
server {
...
location /images/ {
if (-f $document_root$new_uri) {
return 301 $new_uri;
}
try_files $uri =404;
}
}
Always verify your configuration with:
nginx -t
for syntax validation- Actual requests with
curl -I
to check headers - Error log monitoring during rollout
When migrating image storage locations in web applications, we often need to handle legacy URLs while ensuring proper fallback behavior. Here's a common case:
# Old image path (might not exist)
/images/products/123.png
# New image path (might exist)
/website_images/products/123.png
We want Nginx to:
- First check if /images/... exists
- If not, check if /website_images/... exists
- Only rewrite if the new location exists
- Fall back to 404 if neither exists
For Nginx versions without try_files support, we can use rewrite with file checks:
location /images/ {
# Check if original file exists
if (-f $request_filename) {
break;
}
# Capture the path after /images/
if ($uri ~ ^/images/(.*)$) {
set $image_path $1;
# Check if new location exists
if (-f $document_root/website_images/$image_path) {
rewrite ^/images/(.*)$ /website_images/$1 last;
}
}
# Fall through to 404 if no matches
}
Here's a full server block implementation:
server {
listen 80;
server_name example.com;
root /var/www/html;
location / {
try_files $uri $uri/ =404;
}
location /images/ {
# Check original file first
if (-f $request_filename) {
break;
}
# Extract path component
if ($uri ~ ^/images/(.*)$) {
set $image_path $1;
set $new_path /website_images/$image_path;
# Verify new location exists
if (-f $document_root$new_path) {
rewrite ^ $new_path last;
}
}
# No matches - return 404
return 404;
}
}
For high-traffic sites, consider these optimizations:
# Map approach (more efficient than multiple ifs)
map $uri $new_image_path {
~^/images/(?.*)$ /website_images/$path;
}
server {
# ...
location /images/ {
if (-f $request_filename) {
break;
}
if ($new_image_path) {
rewrite ^ $new_image_path last;
}
return 404;
}
}
Verify with these test cases:
# Case 1: Old path exists
curl -I http://example.com/images/existing.png
# Case 2: Only new path exists
curl -I http://example.com/images/moved.png
# Case 3: Neither exists
curl -I http://example.com/images/nonexistent.png
Remember to reload Nginx after changes:
nginx -s reload