Skip to content

Instantly share code, notes, and snippets.

@arjones
Forked from mendelgusmao/gist:2356310
Created September 19, 2013 17:13
Show Gist options
  • Save arjones/6626639 to your computer and use it in GitHub Desktop.
Save arjones/6626639 to your computer and use it in GitHub Desktop.
# based on http://uberblo.gs/2011/06/high-performance-url-shortening-with-redis-backed-nginx
# using code from http://stackoverflow.com/questions/3554315/lua-base-converter
# "database scheme"
# database 0: id ~> url
# database 1: id ~> hits
# database 2: id ~> [{referer|user_agent}]
# database 3: id ~> hits (when id is not found)
# database 4: id ~> [{referer|user_agent}] (when id is not found)
# database 5: key "count" storing the number of shortened urls; the id is generated by (this number + 1) converted to base 62
server {
location ~ ^/retrieve$ {
internal;
redis2_query get $request_uri;
redis2_pass 127.0.0.1:6379;
}
location ~ ^/count$ {
internal;
redis2_query select 5;
redis2_query get count;
redis2_pass 127.0.0.1:6379;
}
location ~ ^/history$ {
internal;
redis2_query select 1;
redis2_query incr $request_uri;
redis2_query select 2;
redis2_query rpush $request_uri "$http_referer|$http_user_agent";
redis2_pass 127.0.0.1:6379;
}
location ~ ^/notfound$ {
internal;
redis2_query select 3;
redis2_query incr $request_uri;
redis2_query select 4;
redis2_query rpush $request_uri "$http_referer|$http_user_agent";
redis2_pass 127.0.0.1:6379;
}
location ~ ^/store$ {
internal;
redis2_query select 0;
set_unescape_uri $id $arg_id;
set_unescape_uri $url $arg_url;
redis2_query set $id $url;
redis2_query select 5;
redis2_query incr count;
redis2_pass 127.0.0.1:6379;
}
location ~ ^/shorten/(?<url>.*)$ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
add_header Content-Type text/plain;
content_by_lua '
local parser = require "redis.parser"
local res = ngx.location.capture("/count")
local results, type = parser.parse_replies(res.body, 2)
basen = function(n, b)
n = math.floor(n)
if not b or b == 10 then return tostring(n) end
local digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
local t = {}
local sign = ""
if n < 0 then
sign = "-"
n = -n
end
repeat
local d = (n % b) + 1
n = math.floor(n / b)
table.insert(t, 1, digits:sub(d, d))
until n == 0
return sign .. table.concat(t,"")
end
local id = basen(results[2][1] + 1, 62)
ngx.location.capture("/store",
{ args = { id = "/"..tostring(id), url = ngx.var.url } }
)
ngx.say("http://" .. ngx.var.host .. "/" .. id)
';
}
location / {
content_by_lua '
local parser = require "redis.parser";
local res = ngx.location.capture("/retrieve");
local href, type = parser.parse_reply(res.body);
if type == parser.ERROR_REPLY or href == nil then
ngx.location.capture("/notfound");
ngx.exit(ngx.HTTP_NOT_FOUND);
else
ngx.location.capture("/history");
ngx.redirect(href);
end
';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment