#!/usr/bin/perl use Mojolicious::Lite; use String::Random; use Mojo::Pg; use Arthas::Defaults::520; my $version = '1.0.0'; my $config = { db => { host => 'localhost', name => 'cgshorten', user => 'dbuser', pwd => 'dbpass', }, auth => 'writepass', }; get '/' => sub($self) { return $self->render(text => '_'); }; get '/:shortcode' => [shortcode => qr/[A-Za-z0-9]{8}/] => sub($self) { my $link = $self->pg->db->query('select targeturl from links where shortcode = ?', $self->stash->{shortcode})->hash; if (defined $link) { $self->res->code(303); return $self->redirect_to( $link->{targeturl} ); } return $self->render(text => 'Notfound-shortcode'); }; post '/create' => sub($self) { my $args = $self->req->json; my $db = $self->pg->db; # Handle obvious error cases return $self->mkerror('invalid-JSON-content') if !defined $args; return $self->mkerror('invalid-auth-information') if $args->{auth} ne $config->{auth}; return $self->mkerror('please-provide-URL') if !$args->{targeturl}; my $targeturl = Mojo::URL->new( $args->{targeturl} ); return $self->mkerror('invalid-URL') if !defined $targeturl; return $self->mkerror('invalid-URL-scheme') if $targeturl->scheme ne 'http' && $targeturl->scheme ne 'https'; my $link = $db->query('select shortcode from links where targeturl = ?', $targeturl)->hash; if (defined $link) { return $self->render('json', { status => 'ok', action => 'fetched', shortcode => $link->{shortcode}, shorturl => $self->url_for("/$link->{shortcode}")->to_abs, }); } my $string_gen = String::Random->new; my $shortcode = $string_gen->randregex('[A-Za-z0-9]{8}'); my $saved = 0; my $loopcount = 0; while ( !$saved ) { if ( $loopcount == 10 ) { return $self->mkerror('too-much-recursion-in-insert'); } try { $db->query('insert into links (shortcode, targeturl) values (?, ?)', $shortcode, $targeturl); $saved = 1; } catch { die $_ if $_ !~ m/duplicate\s+key/; }; $loopcount++; } return $self->render('json', { status => 'ok', action => 'created', shortcode => $shortcode, shorturl => $self->url_for("/$shortcode")->to_abs, }); }; helper mkerror => sub { my ($self, $error) = @_; return $self->render('json', { status => 'error', error => $error, }); }; helper pg => sub { state $pg = Mojo::Pg->new("postgresql://$config->{db}->{user}:$config->{db}->{pwd}\@$config->{db}->{host}/$config->{db}->{name}?PrintError=0&RaiseError=1"); }; app->start;