Buridans_donkey/web/source/app.d

154 lines
3.8 KiB
D
Raw Normal View History

2019-04-26 01:32:48 +02:00
import std.string;
2019-04-27 09:22:02 +02:00
import std.array : array;
2019-04-26 01:32:48 +02:00
import std.random;
import std.file;
import vibe.http.server;
import taggedalgebraic;
struct Error {};
union U {
string[] args;
Error e;
}
alias Result = TaggedUnion!U;
auto shuffle(string[] args, const string t)
2019-04-26 01:32:48 +02:00
{
Result r;
switch(t){
case "mt":
2019-04-26 01:32:48 +02:00
Mt19937 gen;
gen.seed(unpredictableSeed);
args.randomShuffle(gen);
break;
case "x":
2019-04-26 01:32:48 +02:00
Xorshift32 gen;
gen.seed(unpredictableSeed);
args.randomShuffle(gen);
break;
case "du":
2019-04-26 01:32:48 +02:00
auto gen = DevRandomGen!"/dev/urandom"();
args.randomShuffle(gen);
break;
case "dr":
2019-04-26 01:32:48 +02:00
auto gen = DevRandomGen!"/dev/random"();
args.randomShuffle(gen);
break;
default:
r = Error();
return r;
2019-04-26 01:32:48 +02:00
}
r = args;
return r ;
2019-04-26 01:32:48 +02:00
}
template DevRandomGen(string gen)
2019-04-27 09:22:59 +02:00
if (gen == "/dev/random" || gen == "/dev/urandom")
2019-04-26 01:32:48 +02:00
{
struct DevRandomGen
{
alias UIntType = uint;
public:
enum bool isUniformRandom = true;
enum empty = false;
/// Smallest generated value.
enum UIntType min = 0;
/// Largest generated value.
enum UIntType max = ubyte.max;
string src = gen;
void seed(UIntType x0) @safe pure nothrow @nogc {}
void popFront() @safe pure nothrow @nogc {}
@property
UIntType front() const { return (cast(ubyte[])(src.read(ubyte.sizeof)))[0]; }
@property
typeof(this) save() @safe pure nothrow @nogc { return this; }
}
}
2019-04-27 10:04:00 +02:00
enum firstPage = `<h1> Buridan's Donkey </h1>
<blockquote>
...a man, being just as hungry as thirsty, and placed in between food and drink, must necessarily remain where he is and starve to death.
</blockquote>
<p> This is the Buridan's Donkey main page.</p>
<p> Do not be afraid to ask for the help of the Donkey</p>
<p> you have four possibilities:<ul>
<li><a href="/x/true,false">/x/true,false</a>: to use Xorshift</li>
<li><a href="/mt/true,false">/mt/true,false</a>: to use Mersenne Twister</li>
<li><a href="/du/true,false">/du/true,false</a>: to use /dev/urandom</li>
<li><a href="/dr/true,false">/dr/true,false</a>: to use /dev/random</li>
</ul></p>
`;
void indexPage(scope HTTPServerRequest req, scope HTTPServerResponse res)
{
res.writeBody(firstPage);
}
2019-04-26 01:32:48 +02:00
void handleRequest(scope HTTPServerRequest req, scope HTTPServerResponse res)
{
2019-04-27 09:23:23 +02:00
void error(){
2019-04-27 10:04:00 +02:00
immutable resp = "Invalid request.<br>For usage see <a href=\"/\">main page</a>";
2019-04-27 09:23:23 +02:00
res.statusCode = 400;
2019-04-27 10:04:00 +02:00
res.writeBody(resp);
2019-04-27 09:23:23 +02:00
}
2019-04-27 10:04:00 +02:00
res.headers["Content-Type"] = "text/html";
if(req.path == "/" || req.path == "/index.html")
return indexPage(req, res);
2019-04-26 01:32:48 +02:00
immutable path = req.requestPath.bySegment.array;
2019-04-27 09:23:23 +02:00
if(path.length != 3){// path[0] == ""
error();
return ;
}
auto engine = path[1].name;
auto args = path[2].name.split(",");
2019-04-26 01:32:48 +02:00
const result = shuffle(args, engine);
2019-04-27 10:03:53 +02:00
2019-04-27 09:23:23 +02:00
result.visit!((string [] r) {
immutable body = "Asino says:</br>" ~
(r.length == 2 ?
r[0] :
"<ul><li>" ~ r.join("</li><li>") ~ "</ul>");
2019-04-27 09:23:23 +02:00
res.writeBody(body);
},
(Error e) { error(); }
);
2019-04-26 01:32:48 +02:00
}
2019-04-27 09:35:29 +02:00
void main(string[] argv)
2019-04-26 01:32:48 +02:00
{
2019-04-27 09:35:29 +02:00
import std.getopt;
import vibe.core.core : runEventLoop, lowerPrivileges;
ushort port = 8080;
string host = "127.0.0.1";
auto rslt = getopt(argv,
"port|p", "Bind to this port.", &port,
"host|H", "Listen to this interface.", &host,
);
if (rslt.helpWanted){
defaultGetoptPrinter("Some information about the program.",
rslt.options);
return;
}
2019-04-26 01:32:48 +02:00
auto settings = new HTTPServerSettings;
2019-04-27 09:35:29 +02:00
settings.port = port;
settings.bindAddresses = [host];
2019-04-26 01:32:48 +02:00
listenHTTP(settings, &handleRequest);
2019-04-27 09:35:29 +02:00
lowerPrivileges();
runEventLoop();
2019-04-26 01:32:48 +02:00
}