user
The job of a URL shortener is to take a long URL (e.g. "https://www.cockroachlabs.com/docs/stable/build-a-go-app-with-cockroachdb.html") and turn it into something shorter (e.g. "https://bit.ly/2QLUQIu").

A simple URL shortener with no special rules is very simple and consists of 2 endpoints:

* One to generate a short version of a URL given a long version of a URL.
* One to handle a call to the short version of a URL and redirect the user to the long (original) version of the URL.

Create a simple URL shortening API with the following endpoints:

**POST /**

A POST endpoint that accepts a JSON body describing the URL to shorten. Your URL shortener should generate a short version of the URL and keep track of the mapping between short and long URLs. For example:

```
   $ curl -X POST 'localhost:8080' \
   -H 'Content-Type: application/json' \
   -d '{
       "long": "https://www.cockroachlabs.com/docs/stable/build-a-go-app-with-cockroachdb.html"
   }'

```

Should returning something similar to:

```
   http://localhost:8080/9eXmFnuj

```

**GET /:short**

A GET endpoint that accepts a short version of the URL in the URL path and redirects the user to the original URL. For example:

```
   $ curl -L http://localhost:3000/9eXmFnuj

```

Should redirect the user to the original URL:

```
   <!DOCTYPE html>
   <html lang="en">
   ...

```

**Rules**:

* Store the short -> long mappings in any way you like. In-memory is fine.
* There are no auth requirements. Your API can be completely open.
assistant
(formerly Perl 6)

**Works with**: Rakudo version 2019.11

As there is no requirement to obfuscate the shortened urls, I elected to just use a simple base 36 incremental counter starting at "0" to "shorten" the urls.

Sets up a micro web service on the local computer at port 10000. Run the service, then access it with any web browser at address localhost:10000 . Any saved urls will be displayed with their shortened id. Enter a web address in the text field to assign a shortened id. Append that id to the web address to automatically be redirected to that url. The url of **this** page is entered as id 0, so the address: " localhost:10000/0 " will redirect to here, to this page.

The next saved address would be accessible at localhost:10000/1 . And so on.

Saves the shortened urls in a local json file called urls.json so saved urls will be available from session to session. No provisions to edit or delete a saved url. If you want to edit the saved urls, edit the urls.json file directly with some third party editor then restart the service.

There is **NO** security or authentication on this minimal app. Not recommended to run this as-is on a public facing server. It would not be too difficult to *add* appropriate security, but it isn't a requirement of this task. Very minimal error checking and recovery.

```
# Persistent URL storage
use JSON::Fast;

my $urlfile = './urls.json'.IO;
my %urls = ($urlfile.e and $urlfile.f and $urlfile.s) ??
  ( $urlfile.slurp.&from-json ) !!
  ( index => 1, url => { 0 => 'http://rosettacode.org/wiki/URL_shortener#Raku' } );

$urlfile.spurt(%urls.&to-json);

# Setup parameters
my $host = 'localhost';
my $port = 10000;

# Micro HTTP service
use Cro::HTTP::Router;
use Cro::HTTP::Server;

my $application = route {
    post -> 'add_url' {
        redirect :see-other, '/';
        request-body -> (:$url) {
            %urls<url>{ %urls<index>.base(36) } = $url;
            ++%urls<index>;
            $urlfile.spurt(%urls.&to-json);
        }
    }

    get -> {
        content 'text/html', qq:to/END/;
        <form action="http://$host:$port/add_url" method="post">
        URL to add:</br><input type="text" name="url"></br>
        <input type="submit" value="Submit"></form></br>
        Saved URLs:
        <div style="background-color:#eeeeee">
        { %urls<url>.sort( +(*.key.parse-base(36)) ).join: '</br>' }
        </div>
        END
    }

    get -> $short {
        if my $link = %urls<url>{$short} {
            redirect :permanent, $link
        }
        else {
            not-found
        }
    }
}

my Cro::Service $shorten = Cro::HTTP::Server.new:
    :$host, :$port, :$application;

$shorten.start;

react whenever signal(SIGINT) { $shorten.stop; exit; }

```