使用D,我将如何监听传入的HTTP流量并对其进行响应?
例如(伪代码):
socket = new socket("locahost", 80)
socket.onRequestRecevied(handleRequest);
function response handleRequest(request) {
//do something with the request and respond
request.respond("hello world")
}
我知道除此之外还有很多内容,但我无法找到许多资源来响应传入的http请求。
编辑: 我目前的尝试只产生了“无法创建套接字:不允许操作”等异常。这可能意味着我正确地做了,但我只是收到系统错误信息。
答案 0 :(得分:5)
它与侦听正常的传入TCP连接并响应它们相同:
import std.socket;
Socket s = new TcpSocket(AddressFamily.INET);
s.bind(new InternetAddress("0.0.0.0", 80));
s.listen(8);
while (true) {
Socket conn=s.accept();
//handle incoming message (I'm putting it in a task pool to handle ;) )
taskPool.put(task!handleHttp(conn));
}
handleHttp(Socket)
包含接收http请求的逻辑,并按照http标准发送响应(你必须找到你的自己)
答案 1 :(得分:5)
标准库中目前没有HTTP服务器。 Adam Ruppe有some very good code on Github用于Web工作,但它目前不包括独立的Web服务器。
下面的程序是一个简单的单线程基本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);
}
答案 2 :(得分:1)
有一个名为G-Wan的多线程(基于事件的)Web服务器,它支持本机 D脚本。
我从未将它与'D'脚本一起使用,只使用了符合预期的C ++脚本。