Reputation: 251
I have the following configuration of nginx that hosts my image service:
upstream thumbor {
server localhost:8888;
}
server {
listen 80;
server_name my.imageserver.com;
client_max_body_size 10M;
rewrite_log on;
location ~ /images {
if ($arg_width="10"){
rewrite ^/images(/.*)$ /unsafe/$1 last;
}
rewrite ^/images(/.*)$ /unsafe/$1 last;
}
location ~ /unsafe {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://thumbor;
proxy_redirect off;
}
location = /favicon.ico {
return 204;
access_log off;
log_not_found off;
}
}
I am trying to rewrite the following urls:
from
to
which is quite easy, the problem begins when I want to allow query string that should go to the path of the url like so:
from
to
Also it will be better if the order of the query strings won't matter.
I tried using: $arg_width but it didn't seem to work.
Using nginx 1.6.1 on ubuntu.
Help would be much much appreciated.
Upvotes: 2
Views: 9534
Reputation: 12775
You need as scripting option that can evaluate the input and construct the rewrite URL. I use the third party Nginx Lua Module for such logic.
You will need to compile the module into Nginx after installing Lua or preferably, LuaJit on your machine.
Alternatively, you can install Openresty which is Nginx bundled with a few modules that completely transforms the Nginx into a full web application server. Openresty will take care of Lua/LuaJit dependencies during installation.
If you have this in place, this should do the job for you:
upstream thumbor {
server localhost:8888;
}
server {
[...]
location ~ ^/images {
rewrite_by_lua '
-- Use local variables to limit their scope to this location block
local i, j, key, val, args, dimension, modetype, tempheight, replacement
-- We only go ahead if there are request arguments to start with
if ngx.var.is_args then
-- Get the request arguments
-- These are loaded into a Lua table of the form, { a = 1, b = 2, c = 3 }
args = ngx.req.get_uri_args()
-- Loop through the args table and build our replacement string
for key, val in pairs(args) do
if key == "width" then
if tempheight then
dimension = val .. "x" .. tempheight
else
dimension = val
end
elseif key == "height" then
if dimension then
dimension = dimension .. "x" .. val
else
tempheight = val
end
elseif key == "mode" then
modetype = val
end
end
-- Construct the replacement string.
replacement = "/unsafe/" .. dimension .. "/" .. modetype .. "/"
-- Replace "/images/" in the request url with the replacement string.
local newuri, n, err = ngx.re.sub(ngx.unescape_uri(ngx.var.request_uri), "/images/", replacement, "io")
-- If there is a new string, then redirect to the new URL
if newuri then
return ngx.redirect(newuri, 301)
end
end
';
}
location ~ /unsafe {
[...]
proxy_pass http://thumbor;
}
[...]
}
Upvotes: 2
Reputation: 572
You can use the arg_name
parameter, and you can get rid of location
block:
rewrite ^/images/(.*)$ /unsafe/$1;
# WARNING: Here we suppose that when we have a "mode" parameter, we have
# width and height paremeters too
if ($arg_mode) {
rewrite ^/unsafe/(.*)$ /images/unsafe/smart/$arg_mode/${arg_width}x${arg_height}/$1 last;
}
Upvotes: 2
Reputation: 30496
Working with query arguments is always hard (this is also true with Apache).
But in your example when you do:
location ~ /images {
if ($arg_width="10"){
rewrite ^/images(/.*)$ /unsafe/$1 last;
}
rewrite ^/images(/.*)$ /unsafe/$1 last;
}
I do not see any difference between the 2 rewrites... so that's maybe why it is not working.
Anyway you could maybe try something like that (based on this thread):
location ^~ /images {
# get there only if we have a query string
if ($is_args) {
set $width "";
set $height "";
if ($args ~* "(?:^|&)width=([^&]+)") {
set $width $1;
}
if ($args ~* "(?:^|&)height=([^&]+)") {
set $height $1;
}
# string concatenation using sort of bash syntax
set $dim "${width}x${height}";
# maybe we should add a control here on $dim !='x'...
# the ? here prevent query string from being appended
rewrite ^/images(/.*)$ /unsafe/$dim/$1? last;
}
rewrite ^/images(/.*)$ /unsafe/$1 last;
}
location ~ /unsafe {
(...)
Upvotes: 4