Skip to content

Instantly share code, notes, and snippets.

@fuchsi
Last active October 11, 2015 00:08
Show Gist options
  • Save fuchsi/3772106 to your computer and use it in GitHub Desktop.
Save fuchsi/3772106 to your computer and use it in GitHub Desktop.
Simple URL-Shortener
#!/usr/bin/env perl
use Mojolicious::Lite;
use Math::BaseConvert qw(hex);
use Digest::CRC qw(crc32);
use Cache::Memcached;
get '/' => sub {
my $self = shift;
$self->render('index');
};
post '/new' => sub {
my $self = shift;
my $url = $self->param('url');
if ($url =~ /^https?:\/\/.*/) {
my $short_url = &gen_hash($url);
if (&store_hash($short_url, $url)) {
$self->stash(url => $url);
$self->stash(short => $short_url);
$self->render('new');
} else {
$self->render('error2');
}
} else {
$self->render('error');
}
};
get '/:hash' => sub {
my $self = shift;
my $hash = lc($self->param('hash'));
my $url = &find_hash($hash);
if ($url) {
$self->redirect_to($url);
} else {
$self->render('index');
}
};
sub find_hash {
my $hash = shift;
my $url;
our $memd;
if (($url = $memd->get($hash))) {
return $url;
}
open(my $FH, "urls.lst") || return 0;
my %table;
while (<$FH>) {
chomp;
my @t = split(/ /, $_, 2);
$table{$t[0]} = $t[1];
$memd->add($t[0], $t[1]);
}
close($FH);
$url = $table{$hash};
return $url;
}
sub store_hash {
my ($hash, $url) = @_;
if (&find_hash($hash)) {
return 1;
}
open(my $FH, "+<" ,"urls.lst") || return 0;
my %table;
our $memd;
while (<$FH>) {
my @t = split(/ /, $_, 2);
$table{$t[0]} = $t[1];
}
$table{$hash} = $url;
foreach (sort(keys(%table))) {
print $FH "$_ " . $table{$_} . "\n";
$memd->add($_, $url);
}
close($FH);
$memd->set($hash, $url);
return 1;
}
sub gen_hash {
my $url = shift;
# DJB33X (Hashes waren zu lang, deshalb CRC32)
# my $hash = 5381;
# my @arr = split(/(.{1})/, $url);
# foreach (@arr) {
# if ($_ eq '') {
# next;
# }
# $hash = (($hash << 5) + $hash) ^ ord($_);
# }
# return lc(hex($hash));
return lc(hex(crc32($url)));
}
our $memd = new Cache::Memcached {
'servers' => [ "127.0.0.1:11211" ],
'compress_threshold' => 10_000,
};
app->config(hypnotoad => {listen => ['http://127.0.0.1:50001']});
app->start;
__DATA__
@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<style type="text/css">
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: Verdana, Helvetica, "Bitstream Vera Sans", sans-serif;
font-size: 10pt;
}
#app {
text-align: center;
width: 600px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -300px;
margin-top: -50px;
border: 1px solid #555555;
border-radius: 5px 5px 5px 5px;
background-color: #BFD9FF;
}
#url {
width: 90%;
border: 1px solid #555555;
border-radius: 2px 2px 2px 2px;
font-family: Verdana, Helvetica, "Bitstream Vera Sans", sans-serif;
font-size: 10pt;
padding: 1px;
}
button:hover,
#url:hover,
#url:focus {
border-color: #80B3FF;
}
button {
background-color: #EEEEEE;
border: 1px solid #555555;
border-radius: 2px 2px 2px 2px;
font-family: Verdana, Helvetica, "Bitstream Vera Sans", sans-serif;
font-size: 10pt;
padding: 3px;
margin: 5px;
}
</style>
</head>
<body>
<div id="app">
<%= content %>
</div>
</body>
</html>
@@ index.html.ep
% title 'Simple URL Shortener';
% layout 'default';
<form action="/new" method="post">
<label for="url">
URL to shorten:
</label><br />
<input type="text" name="url" id="url" /><br />
<button type="submit">Shorten</button>
</form>
@@ new.html.ep
% title 'Simple URL Shortener';
% layout 'default';
The short URL for<br />
<span style="font-weight: bold;"><%= $url %></span>
<br />is<br />
<a style="font-weight: bold;" href="/<%= $short %>">http://s.bn3t.de/<%= $short %></a>
@@ error.html.ep
% title 'Simple URL Shortener';
% layout 'default';
The URL you entered is not valid!<br />
<a href="/">Back</a>
@@ error2.html.ep
% title 'Simple URL Shortener';
% layout 'default';
An error occured!<br />
<a href="/">Back</a>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment