mco 0.1.48

Rust Coroutine Library like go
Documentation
extern crate bytes;
extern crate httparse;
#[macro_use]
extern crate mco;

use bytes::BufMut;
use httparse::Status;
use mco::net::TcpListener;
use std::io::{Read, Write};

// This example is for demonstration only and is suitable for production environment please move on
// example see https://github.com/co-rs/mco-http/tree/main/examples
fn main() {
    println!("bind http://127.0.0.1:3000");
    let listener = TcpListener::bind("0.0.0.0:3000").unwrap();
    while let Ok((mut stream, _)) = listener.accept() {
        co!(move || {
            let mut buf = Vec::new();
            let mut path = String::new();

            loop {
                if let Some(i) = req_done(&buf, &mut path) {
                    let response = match &*path {
                        "/" => "Hello, World!\n",
                        "/hello" => "Hello, World!\n",
                        "/quit" => std::process::exit(1),
                        _ => "Cannot find page\n",
                    };

                    let s = format!(
                        "\
                         HTTP/1.1 200 OK\r\n\
                         Server: mco\r\n\
                         Content-Length: {}\r\n\
                         date: 1-1-2000\r\n\
                         \r\n\
                         {}",
                        response.len(),
                        response
                    );

                    stream
                        .write_all(s.as_bytes())
                        .expect("Cannot write to socket");

                    buf = buf.split_off(i);
                } else {
                    let mut temp_buf = vec![0; 512];
                    match stream.read(&mut temp_buf) {
                        Ok(0) => return, // connection was closed
                        Ok(n) => buf.put(&temp_buf[0..n]),
                        Err(err) => {
                            println!("err = {:?}", err);
                            break;
                        }
                    }
                }
            }
        });
    }
}

fn req_done(buf: &[u8], path: &mut String) -> Option<usize> {
    let mut headers = [httparse::EMPTY_HEADER; 16];
    let mut req = httparse::Request::new(&mut headers);

    if let Ok(Status::Complete(i)) = req.parse(buf) {
        path.clear();
        path.push_str(req.path.unwrap_or("/"));
        return Some(i);
    }

    None
}