В стандартной библиотеке нет HTTP-сервера.У Adam Ruppe есть некоторый очень хороший код на Github для веб-работы, но в настоящее время он не включает автономный веб-сервер.
Программа, представленная ниже, представляет собой простой однопоточныйHTTP-сервер, в образовательных целях.Создание правильного HTTP-ответа все еще зависит от вас;но, по крайней мере, он анализирует заголовок и дает вам возможность ответить на основании деталей запроса.
import std.algorithm;
import std.conv;
import std.stdio;
import std.socket;
import std.string;
// usage: ./server port
void main(string[] args)
{
enum BACKLOG = 8;
ushort PORT = to!ushort(args[1]);
Socket s = new TcpSocket(AddressFamily.INET);
s.bind(new InternetAddress("0.0.0.0", PORT));
s.listen(BACKLOG);
scope (exit)
{
s.shutdown(SocketShutdown.BOTH);
s.close();
}
while (true)
{
debug writeln("waiting...");
Socket conn = s.accept();
scope (exit)
{
conn.shutdown(SocketShutdown.BOTH);
conn.close();
}
try
{
handleHttp(conn);
}
catch (Throwable e)
{
stderr.writeln("thrown: ", e);
}
}
}
void handleHttp(Socket conn)
{
// Make a buffer big enough to read a full HTTP header. My approach here is to
// read the header in its entirety before proceeding. This isn't production
// quality, but good enough for some applications.
ubyte[8192] buf; // big enough for some purposes...
size_t position, headerEnd, len, newpos;
// Receive the whole header before parsing it.
while (true)
{
len = conn.receive(buf[position..$]);
if (len == 0) // empty request
return;
newpos = position + len;
headerEnd = countUntil(buf[position..newpos], "\r\n\r\n");
position = newpos;
if (headerEnd >= 0)
break;
}
// Anything beyond headerEnd+4 is part of the request body. For now, bail:
// no POSTs or PUTs allowed. Feel free to remove the assert & implement them!
assert (position-(headerEnd+4) == 0,
"Sorry, only content-free requests are supported.");
// Now parse the header.
auto lines = splitter(buf[0..headerEnd], "\r\n");
string request_line = cast(string) lines.front;
lines.popFront;
debug writeln(request_line);
// a very simple Header structure.
struct Pair
{
string key, value;
this(ubyte[] line)
{
auto tmp = countUntil(line, ": ");
key = cast(string) line[0..tmp]; // maybe down-case these?
value = cast(string) line[tmp+2..$];
}
}
Pair[] headers;
foreach(line; lines)
headers ~= Pair(line);
auto tmp = splitter(request_line, ' ');
string method = tmp.front; tmp.popFront;
string url = tmp.front; tmp.popFront;
string protocol = tmp.front; tmp.popFront;
debug writefln("%s, %s, %s", method, url, protocol);
// Prepare a response, and send it
string resp = join(["HTTP/1.1 200 OK",
"Content-Length: 2",
"Content-Type: text/plain",
"Connection: close",
"",
"OK"],
"\r\n");
conn.send(cast(ubyte[]) resp);
}