Open3

Reading "Real World HTTP" in Rust

yuheitomiyuheitomi

第1章のシンプルなエコーサーバー。

use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};

fn main() {
    let port = ":18888";
    let listener =
        TcpListener::bind(format!("127.0.0.1{}", port)).expect("Failed to bind connection");
    eprintln!("Listening to... {}", listener.local_addr().unwrap());
    for stream in listener.incoming() {
        let stream = stream.unwrap();
        handle_connection(stream);
    }
}

fn handle_connection(mut stream: TcpStream) {
    let mut buffer = [0; 1024];
    let _size = stream.read(&mut buffer).unwrap();

    let req = String::from_utf8_lossy(&buffer);
    eprintln!("{}", req);

    let response = "HTTP/1.1 200 OK\r\n\r\n<html><body>hello</body></html>";
    let _size = stream
        .write(response.as_bytes())
        .expect("Failed to write to stream");
    stream.flush().expect("Failed to flush");
}
yuheitomiyuheitomi

標準ライブラリ TcpListener TcpSteram をそのまま扱うのでも勉強になりそうだが、lightweight なライブラリを探してみたら tiny_http という crate があった。こんな感じで書ける。

/// Simple echo server using `tiny_http` crate
use tiny_http::{Response, Server};

fn main() {
    let addr = "0.0.0.0:18888";

    let server = Server::http(addr).expect("Failed to initiate server");
    for req in server.incoming_requests() {
        println!(
            "{:?} {:?} {:?}",
            req.http_version(),
            req.method(),
            req.url()
        );
        for header in req.headers() {
            println!("{} {}", header.field, header.value);
        }

        let res = Response::from_string("Hello");
        req.respond(res).unwrap();
    }
}