-
-
Save s1037989/03960207a2b9a9befc6d5f21c0f70adc to your computer and use it in GitHub Desktop.
Tiny URL clone built with Mojolicious in 1 hour
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use Mojolicious::Lite; | |
use Mojo::Pg; | |
use List::Util qw(shuffle); | |
# tiny.conf | |
# { pg => 'postgresql://a:b@c/d', }; | |
# Get a quick and free tiny hosted Postgresql database at | |
# http://elephantsql.com | |
plugin 'Config'; | |
helper pg => sub { state $pg = Mojo::Pg->new(shift->config('pg')) }; | |
app->pg->migrations->from_data->migrate; | |
any '/' => sub { | |
my $c = shift; | |
# Check if parameters have been submitted | |
# and if not show the errors | |
my $v = $c->validation; | |
return $c->render unless $v->has_data; | |
$v->required('url')->like(qr/^https?:\/\//); | |
return $c->render if $v->has_error; | |
my $tiny; | |
# If someone already submitted the same URL, use the same tiny code | |
unless ( $tiny = $c->pg->db->query('select * from tiny where url = ?', $v->param('url'))->hash ) { | |
# Otherwise, store the new URL and generate a tiny code based on the shuffling of the URL | |
$tiny = $c->pg->db->query('insert into tiny (id, url) values (left(md5(?), 6), ?) returning *', | |
join('', shuffle(split //, $v->param('url'))), | |
$v->param('url'), | |
)->hash; | |
} | |
app->log->info(sprintf("Add: %s => %s", $tiny->{id}, $tiny->{url})); | |
# Show the same index page, but show the tiny code just created | |
$c->flash($tiny)->redirect_to('index'); | |
} => 'index'; | |
get '/:id' => sub { | |
my $c = shift; | |
# Redirect to the URL on file for the code provided, 404 otherwise | |
return $c->reply->not_found unless my $tiny = $c->pg->db->query('select url from tiny where id = ?', $c->param('id'))->hash; | |
app->log->info(sprintf("Redirect: %s => %s", $c->param('id'), $tiny->{url})); | |
return $c->reply->not_found unless $tiny->{url}; | |
$c->redirect_to($tiny->{url}); | |
} => 'tiny'; | |
app->start or exit unless app->mode =~ /^test/; | |
__DATA__ | |
@@ migrations | |
-- 1 up | |
create table tiny (id text, url text); | |
create unique index on tiny (id); | |
-- 1 down | |
drop table tiny; | |
@@ index.html.ep | |
% layout 'default'; | |
% title 'Welcome'; | |
% if ( my $id = flash 'id' ) { | |
Your Tiny URL is: <%= link_to url_for('tiny', {id => $id})->to_abs => begin %><%= url_for('tiny', {id => $id})->to_abs %><%= end %><br> | |
Which maps to: <%= flash 'url' %><br><br> | |
% } | |
%= form_for 'index', (method => 'POST') => begin | |
%= label_for url => 'New Tiny URL (must be a valid URL)' | |
<br> | |
%= text_field 'url', placeholder => 'Enter your URL here' | |
<br> | |
%= submit_button | |
%= end | |
@@ layouts/default.html.ep | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title><%= title %></title> | |
<style> | |
label.field-with-error { color: #dd7e5e } | |
input.field-with-error { background-color: #fd9e7e } | |
</style> | |
</head> | |
<body><%= content %></body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment