AkurAI Build
Menu

Public repository / master

AkurAI-Framework / crates/http/tests/access_log.rs

Latest change 1f2c9f9983d36d42b1f177ad7bcea92a8fe8dc4d - feat: built-in server access log, default on by Ólafur Búi Ólafsson

//! End-to-end: the server stamps the peer address onto each `Request`, and the
//! access log can be switched off. The log line itself goes to stderr (owned by
//! the process, not capturable in-process); its content is covered by the unit
//! tests in `server.rs`.

use akurai_http::{Request, Response, Server};
use std::io::{Read, Write};
use std::net::TcpStream;

/// Send one request and read the full response as a string.
fn roundtrip(addr: std::net::SocketAddr, raw: &str) -> String {
    let mut conn = TcpStream::connect(addr).unwrap();
    conn.write_all(raw.as_bytes()).unwrap();
    let mut resp = String::new();
    conn.read_to_string(&mut resp).unwrap();
    resp
}

#[test]
fn server_stamps_peer_address_on_requests() {
    let server = Server::bind("127.0.0.1:0").unwrap().access_log(false);
    let addr = server.local_addr().unwrap();

    std::thread::spawn(move || {
        server
            .run(|req: &Request| {
                let peer = req
                    .peer
                    .map_or_else(|| "none".to_string(), |p| p.to_string());
                Response::ok().with_text(&format!("peer={peer}"))
            })
            .unwrap();
    });

    let resp = roundtrip(addr, "GET / HTTP/1.1\r\nHost: x\r\n\r\n");
    assert!(resp.starts_with("HTTP/1.1 200 OK\r\n"), "got: {resp:?}");
    // The handler saw a real socket address, and it is a loopback peer.
    assert!(resp.contains("peer=127.0.0.1:"), "got: {resp:?}");
}

#[test]
fn parsed_head_has_no_peer_outside_a_connection() {
    let req = Request::parse_head(b"GET / HTTP/1.1\r\n\r\n").unwrap();
    assert_eq!(req.peer, None);
}