2011-10-04 7 views
7

Sử dụng D, làm cách nào để lắng nghe lưu lượng truy cập HTTP đến và phản hồi lại?Sử dụng D, làm cách nào để lắng nghe các yêu cầu HTTP đến và trả lời chúng?

Ví dụ (trong giả):

socket = new socket("locahost", 80) 
socket.onRequestRecevied(handleRequest); 

function response handleRequest(request) { 
    //do something with the request and respond 
    request.respond("hello world") 
} 

Tôi biết có rất nhiều điều hơn thế, nhưng tôi đã không thể tìm thấy nhiều tài nguyên trên đáp ứng yêu cầu http đến.

CHỈNH SỬA: Nỗ lực hiện tại của tôi chỉ mang lại ngoại lệ như "Không thể tạo ổ cắm: Thao tác không được phép". điều này có nghĩa là tôi đang làm đúng nhưng chỉ đơn giản là nhận được thông báo lỗi hệ thống.

+0

Bạn có quyền nghe trên cổng 80 hoặc bất kỳ cổng cấp thấp nào khác không? Hãy thử với cổng 8080 hoặc cái gì khác không nằm trong phạm vi hạn chế. – gmfawcett

+0

Tôi đã thử nó với cổng 3000. Tôi cũng đã thử nó với 8080 và một vài người khác. –

Trả lời

5

nó giống như nghe các kết nối đến TCP bình thường và đối phó với họ:

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)); 
    } 

với handleHttp(Socket) chứa logic để tiếp nhận các yêu cầu http và gửi câu trả lời theo quy định được các tiêu chuẩn http (bạn sẽ phải tự mình thấy mình)

+0

Điều này có vẻ đang hoạt động. Cảm ơn. –

5

Hiện không có máy chủ HTTP nào trong thư viện chuẩn. Adam Ruppe có cho công việc Web, nhưng hiện tại nó không bao gồm một máy chủ Web độc lập.

Chương trình bên dưới là máy chủ HTTP cơ bản, đơn luồng, cho mục đích giáo dục . Việc tạo phản hồi HTTP hợp lệ vẫn tùy thuộc vào bạn; nhưng ít nhất nó phân tích cú pháp tiêu đề và cho bạn cơ hội trả lời dựa trên các chi tiết của yêu cầu .

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); 
} 
+0

Cảm ơn! Bạn không biết làm thế nào để làm cho nó đa luồng? –

1

Có một (event-based) Web server multi-threaded gọi G-Wan mà hỗ trợ mẹ đẻ script D.

Tôi chưa bao giờ sử dụng nó với tập lệnh 'D', chỉ với các tập lệnh C++ mà nó hoạt động như mong đợi.