URL shortener: Difference between revisions

m
m (→‎{{header|JavaScript}}: Added a Works With tag to differentiate Node from pure JS)
m (→‎{{header|Wren}}: Minor tidy)
 
(7 intermediate revisions by 4 users not shown)
Line 43:
{{libheader| kemal}}
 
<langsyntaxhighlight lang="ruby">require "kemal"
 
CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".chars
Line 66:
end
 
Kemal.run</langsyntaxhighlight>
 
=={{header|Delphi}}==
Line 78:
{{libheader| Inifiles}}
Highly inspired in [[#Go]]
<syntaxhighlight lang="delphi">
<lang Delphi>
program URLShortenerServer;
 
Line 244:
 
Manager.Free;
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 251:
</pre>
=={{header|Go}}==
<langsyntaxhighlight lang="go">// shortener.go
package main
 
Line 319:
db := make(database)
log.Fatal(http.ListenAndServe(host, db))
}</langsyntaxhighlight>
 
{{out}}
Line 355:
=={{header|JavaScript}}==
{{works with|Node.js}}
<langsyntaxhighlight JavaScriptlang="javascript">#!/usr/bin/env node
 
var mapping = new Map();
Line 402:
res.writeHead(404);
res.end();
}).listen(8080);</langsyntaxhighlight>
{{out}}
<pre>$ curl -X POST http://localhost:8080/ -H "Content-Type: application/json" --data "{\"long\":\"https://www.example.com\"}"
Line 411:
=={{header|Julia}}==
Assumes an SQLite database containing a table called LONGNAMESHORTNAME (consisting of two string columns) already exists.
<langsyntaxhighlight lang="julia">using Base64, HTTP, JSON2, Sockets, SQLite, SHA
 
function processpost(req::HTTP.Request, urilen=8)
Line 456:
const localport = 3000
run_web_server(serveraddress, localport)
</syntaxhighlight>
</lang>
 
=={{header|Objeck}}==
<syntaxhighlight lang="objeck">use Collection.Generic;
use Data.JSON;
use Web.HTTP;
 
class Shortner from HttpRequestHandler {
@url_mapping : static : Hash<String, String>;
 
function : Init() ~ Nil {
@url_mapping := Hash->New()<String, String>;
}
 
New() {
Parent();
}
 
function : Main(args : String[]) ~ Nil {
if(args->Size() = 1) {
Shortner->Init();
WebServer->Serve(Shortner->New()->GetClass(), args[0]->ToInt(), true);
};
}
 
method : ProcessGet(request_url : String, request_headers : Map<String, String>, response_headers : Map<String, String>) ~ Response {
long_url := @url_mapping->Find(request_url);
if(long_url <> Nil) {
response := Response->New(302);
response->SetReason(long_url);
 
return response;
};
return Response->New(404);
}
method : ProcessPost(buffer : Byte[], request_url : String, request_headers : Map<String, String>, response_headers : Map<String, String>) ~ Response {
response : Byte[];
json := JsonParser->New(String->New(buffer));
if(json->Parse()) {
url_json := json->GetRoot()->Get("long");
long_url := url_json->GetValue();
post_fix := "/";
each(i : 6) {
if(Int->Random(1) % 2 = 0) {
post_fix += Int->Random('a', 'z')->As(Char);
}
else {
post_fix += Int->Random('A', 'Z')->As(Char);
};
};
 
short_url := "http://localhost:60013{$post_fix}";
@url_mapping->Insert(post_fix, long_url);
 
response_headers->Insert("Content-type", "application/json");
response := "{ \"short\": \"{$short_url}\" }"->ToByteArray();
};
 
return Response->New(200, response);
}
}</syntaxhighlight>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\URL_shortener.exw
-- ==============================
--
-- Uses a routine originally written for a code minifier, so were you to run this
-- for a long time, you'd get 52 one-character short urls, ie a..z and A..Z, then
-- 3,224 (=52*62) two-character short urls, as 2nd char on can also be 0..9, then
-- 199,888 (=52*62*62) three-character short urls, and so on. The dictionary used
-- is not [yet] saved/reloaded between runs. No attempt is made to re-produce the
-- same short url if the same long url is passed in twice. Nothing remotely like
-- any form of error handling, as per the usual "for clarity".
--
-- Windows only for now (should be straightforward to get it working on linux)
-- (routines in builtins\sockets.e that be windows-only.)
--
-- See sample session output (in a separate terminal) for usage instructions.
-- </span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">sockets</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">json</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAX_QUEUE</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">ESCAPE</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">#1B</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">shortened</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: %d
The shortened URL: http://localhost:8080/%s
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\r\n"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">redirect</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
HTTP/1.1 302 Found
Content-Type: text/html; charset=UTF-8
Content-Length: %d
Location: %s
&lt;a href="%s"&gt;Found&lt;/a&gt;.
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\r\n"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">not_found</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
Content-Length: %d
No such shortened url: http://localhost:8080/%s
"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\r\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">shurl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">response</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lnk</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">url</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">alphabet</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'z'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'a'</span><span style="color: #0000FF;">)&</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">)&</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'9'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">short_id</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">52</span> <span style="color: #000080;font-style:italic;">-- (first char azAZ)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">62</span> <span style="color: #000080;font-style:italic;">-- (subsequent chars azAZ09)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"server started, open http://localhost:8080/ in browser or curl, press Esc or Q to quit\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">sock</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">socket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">AF_INET</span><span style="color: #0000FF;">,</span><span style="color: #000000;">SOCK_STREAM</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pSockAddr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sockaddr_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">AF_INET</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8080</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">bind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sock</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pSockAddr</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">SOCKET_ERROR</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"bind (%v)"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">get_socket_error</span><span style="color: #0000FF;">()})</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">listen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sock</span><span style="color: #0000FF;">,</span><span style="color: #000000;">MAX_QUEUE</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">SOCKET_ERROR</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"listen (%v)"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">get_socket_error</span><span style="color: #0000FF;">()})</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">get_key</span><span style="color: #0000FF;">(),{</span><span style="color: #000000;">ESCAPE</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'q'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'Q'</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">integer</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">select</span><span style="color: #0000FF;">({</span><span style="color: #000000;">sock</span><span style="color: #0000FF;">},{},{},</span><span style="color: #000000;">250000</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">=</span><span style="color: #000000;">SOCKET_ERROR</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"select (%v)"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">get_socket_error</span><span style="color: #0000FF;">()})</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (not timeout)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">peer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">accept</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sock</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ip</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getsockaddr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">peer</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">integer</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">request</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">recv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">peer</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Client IP: %s\n%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">ip_to_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ip</span><span style="color: #0000FF;">),</span><span style="color: #000000;">request</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">request</span><span style="color: #0000FF;">)></span><span style="color: #000000;">5</span> <span style="color: #008080;">and</span> <span style="color: #000000;">request</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">"POST "</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">json</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">request</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'{'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">request</span><span style="color: #0000FF;">)..$]</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">json_data</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">parse_json</span><span style="color: #0000FF;">(</span><span style="color: #000000;">json</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">url</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">extract_json_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">json_data</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"long"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">lnk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">short_id</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">dict_size</span><span style="color: #0000FF;">(</span><span style="color: #000000;">shurl</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">url</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shurl</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">response</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">shortened</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">45</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">request</span><span style="color: #0000FF;">)></span><span style="color: #000000;">4</span> <span style="color: #008080;">and</span> <span style="color: #000000;">request</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">4</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">"GET "</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">lnk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">request</span><span style="color: #0000FF;">[</span><span style="color: #000000;">6</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">request</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">node</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shurl</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">node</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">url</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd_by_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">node</span><span style="color: #0000FF;">,</span><span style="color: #000000;">shurl</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">response</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">redirect</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">url</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">url</span><span style="color: #0000FF;">,</span><span style="color: #000000;">url</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">response</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">not_found</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">49</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lnk</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">else</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- uh?</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bytes_sent</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">send</span><span style="color: #0000FF;">(</span><span style="color: #000000;">peer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">response</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d bytes successfully sent\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bytes_sent</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">shutdown</span><span style="color: #0000FF;">(</span><span style="color: #000000;">peer</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SD_SEND</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- tell curl it's over</span>
<span style="color: #000000;">peer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">closesocket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">peer</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (as does this)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">sock</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">closesocket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sock</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">WSACleanup</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
Sample session output:
<pre>
C:\Program Files (x86)\Phix>curl http://localhost:8080/X
No such shortened url: http://localhost:8000/X
 
C:\Program Files (x86)\Phix>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\"}"
The shortened URL: http://localhost:8000/a
 
C:\Program Files (x86)\Phix>curl http://localhost:8080/a
<a href="https://www.cockroachlabs.com/docs/stable/build-a-go-app-with-cockroachdb.html">Found</a>.
</pre>
Of course if you paste http://localhost:8080/a into a browser (with URL_shortener.exw still running!) it goes to the right place.<br>
Meanwhile, in a separate terminal (with * replaced by $ to avoid comment issues) we get:
<pre>
server started, open http://localhost:8080/ in browser or curl, press Esc or Q to quit
Client IP: 127.0.0.1
GET /a HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.55.1
Accept: $/$
 
 
137 bytes successfully sent
Client IP: 127.0.0.1
POST / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.55.1
Accept: $/$
Content-Type: application/json
Content-Length: 89
 
{"long":"https://www.cockroachlabs.com/docs/stable/build-a-go-app-with-cockroachdb.html"}
126 bytes successfully sent
Client IP: 127.0.0.1
GET /a HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.55.1
Accept: $/$
 
 
276 bytes successfully sent
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/http.l")
(allowed NIL "!short" u)
(pool "urls.db" (6))
Line 470 ⟶ 685:
(commit 'upd)
(respond (pack "http://127.0.0.1:8080/?" K "\n")) ) ) )
(server 8080 "!short")</langsyntaxhighlight>
{{out}}
<pre>
Line 504 ⟶ 719:
===Flask===
{{libheader|Flask}}
<langsyntaxhighlight lang="python">
"""A URL shortener using Flask. Requires Python >=3.5."""
 
Line 689 ⟶ 904:
app.env = "development"
app.run(debug=True)
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 704 ⟶ 919:
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.
 
<syntaxhighlight lang="raku" perl6line># Persistent URL storage
use JSON::Fast;
 
Line 760 ⟶ 975:
 
react whenever signal(SIGINT) { $shorten.stop; exit; }
</syntaxhighlight>
</lang>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|WrenGo}}
{{libheader|Wren-json}}
An embedded program with a Go host so we can use its net/http module.
<syntaxhighlight lang="wren">/* URL_shortener.wren */
 
import "./json" for JSON
import "random" for Random
 
var Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
var MethodPost = "POST"
var MethodGet = "GET"
var StatusBadRequest = 400
var StatusFound = 302
var StatusNotFound = 404
 
var Db = {}
var Rand = Random.new()
 
var GenerateKey = Fn.new { |size|
var key = List.filled(size, null)
var le = Chars.count
for (i in 0...size) key[i] = Chars[Rand.int(le)]
return key.join()
}
 
class ResponseWriter {
foreign static writeHeader(statusCode)
foreign static fprint(str)
}
 
class Request {
foreign static method
foreign static body
foreign static urlPath
}
 
class Http {
foreign static host
 
static serve() {
if (Request.method == MethodPost) {
var body = Request.body
var sh = JSON.parse(body)["long"]
var short = GenerateKey.call(8)
Db[short] = sh
ResponseWriter.fprint("The shortened URL: http://%(host)/%(short)\n")
} else if (Request.method == MethodGet) {
var path = Request.urlPath[1..-1]
if (Db.containsKey(path)) {
redirect(Db[path], StatusFound)
} else {
ResponseWriter.writeHeader(StatusNotFound)
ResponseWriter.fprint("No such shortened url: http://%(host)/%(path)\n")
}
} else {
ResponseWriter.writeHeader(StatusNotFound)
ResponseWriter.fprint("Unsupported method: %(Request.method)\n")
}
}
 
foreign static redirect(url, code)
}</syntaxhighlight>
We now embed this script in the following Go program and build it.
<syntaxhighlight lang="go">/* go build URL_shortener.go */
 
package main
 
import (
"fmt"
wren "github.com/crazyinfin8/WrenGo"
"io/ioutil"
"log"
"net/http"
"strings"
)
 
type any = interface{}
 
var fileName = "URL_shortener.wren"
var host = "localhost:8000"
 
var vm *wren.VM
 
var gw http.ResponseWriter
var greq *http.Request
 
func serveHTTP(w http.ResponseWriter, req *http.Request) {
gw, greq = w, req
wrenVar, _ := vm.GetVariable(fileName, "Http")
wrenClass, _ := wrenVar.(*wren.Handle)
defer wrenClass.Free()
wrenMethod, _ := wrenClass.Func("serve()")
defer wrenMethod.Free()
wrenMethod.Call()
}
 
func writeHeader(vm *wren.VM, parameters []any) (any, error) {
statusCode := int(parameters[1].(float64))
gw.WriteHeader(statusCode)
return nil, nil
}
 
func fprint(vm *wren.VM, parameters []any) (any, error) {
str := parameters[1].(string)
fmt.Fprintf(gw, str)
return nil, nil
}
 
func method(vm *wren.VM, parameters []any) (any, error) {
res := greq.Method
return res, nil
}
 
func body(vm *wren.VM, parameters []any) (any, error) {
res, _ := ioutil.ReadAll(greq.Body)
return res, nil
}
 
func urlPath(vm *wren.VM, parameters []any) (any, error) {
res := greq.URL.Path
return res, nil
}
 
func getHost(vm *wren.VM, parameters []any) (any, error) {
return host, nil
}
 
func redirect(vm *wren.VM, parameters []any) (any, error) {
url := parameters[1].(string)
code := int(parameters[2].(float64))
http.Redirect(gw, greq, url, code)
return nil, nil
}
 
func moduleFn(vm *wren.VM, name string) (string, bool) {
if name != "meta" && name != "random" && !strings.HasSuffix(name, ".wren") {
name += ".wren"
}
return wren.DefaultModuleLoader(vm, name)
}
 
func main() {
cfg := wren.NewConfig()
cfg.LoadModuleFn = moduleFn
vm = cfg.NewVM()
 
responseWriterMethodMap := wren.MethodMap{
"static writeHeader(_)": writeHeader,
"static fprint(_)": fprint,
}
 
requestMethodMap := wren.MethodMap{
"static method": method,
"static body": body,
"static urlPath": urlPath,
}
 
httpMethodMap := wren.MethodMap{
"static host": getHost,
"static redirect(_,_)": redirect,
}
 
classMap := wren.ClassMap{
"ResponseWriter": wren.NewClass(nil, nil, responseWriterMethodMap),
"Request": wren.NewClass(nil, nil, requestMethodMap),
"Http": wren.NewClass(nil, nil, httpMethodMap),
}
 
module := wren.NewModule(classMap)
vm.SetModule(fileName, module)
vm.InterpretFile(fileName)
http.HandleFunc("/", serveHTTP)
log.Fatal(http.ListenAndServe(host, nil))
vm.Free()
}</syntaxhighlight>
{{out}}
Sample output (abbreviated) including building and starting the server from Ubuntu 20.04 terminal and entering a valid and then an invalid shortened URL:
<pre>
$ go build URL_shortener.go
 
$ ./URL_shortener &
 
$ curl -X POST 'localhost:8000'/ \
> -H 'Content-Type: application/json' \
> -d '{
> "long": "https://www.cockroachlabs.com/docs/stable/build-a-go-app-with-cockroachdb.html"
> }'
The shortened URL: http://localhost:8000/RRyYg8tK
 
$ curl -L http://localhost:8000/RRyYg8tK
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Learn how to use CockroachDB from a simple Go application with the Go pgx driver.">
 
....
 
</html>
 
$ curl -L http://localhost:8000/3DOPwhRv
No such shortened url: http://localhost:8000/3DOPwhRv
</pre>
9,482

edits