Problem related to rust code, probably iterators

use std::{
    io::{BufRead, BufReader, Error},
    net::{Ipv4Addr, TcpListener, TcpStream},
    process::exit,
};

struct Headers {
    key: String,
    value: String,
}
struct HttpRequest {
    method: String,
    path: String,
    version: String,
    // headers: Vec<Headers>,
    // body: String,
}

fn parse_request<'a>(mut lines: impl Iterator<Item = String>) -> Result<HttpRequest, Error> {
    let request_line = lines.next().ok_or(Error::new(
        std::io::ErrorKind::InvalidInput,
        "Misisng request line",
    ))?;

    let mut request_line_parts = request_line.split_whitespace();

    let method = request_line_parts
        .next()
        .ok_or(Error::new(
            std::io::ErrorKind::InvalidInput,
            "Method missing",
        ))?
        .to_string();
    let path = request_line_parts
        .next()
        .ok_or(Error::new(std::io::ErrorKind::InvalidInput, "Path missing"))?
        .to_string();
    let version = request_line_parts
        .next()
        .ok_or(Error::new(
            std::io::ErrorKind::InvalidInput,
            "Version missing",
        ))?
        .to_string();

    // let headeres=lines.take_while(|line|)

    Ok(HttpRequest {
        method,
        path,
        version,
    })
}

fn handle_connection(connection: TcpStream) -> Result<(), Error> {
    let peer_addr = connection.peer_addr()?;

    println!("Connected to {}", peer_addr);

    let buf_reader = BufReader::new(connection);

    let mut http_request_iter = buf_reader.lines().map(|l| l.unwrap());

    for l in http_request_iter {
        println!("{}", l);
    }
    println!("Connection close {}", peer_addr);
    Ok(())
}

#[allow(unused)]
fn main() {
    const PORT: u16 = 4221;

    let server = TcpListener::bind((Ipv4Addr::new(0, 0, 0, 0), PORT)).unwrap_or_else(|err| {
        eprintln!("Server: Listen {}", err.to_string());
        exit(1);
    });

    println!("Server listening at {}", server.local_addr().unwrap());

    for connection in server.incoming() {
        match connection {
            Ok(connection) => {
                if let Err(err) = handle_connection(connection) {
                    eprintln!("Some problem with request parsing")
                }
            }
            Err(err) => {
                println!("Could not successfully accept {}", err.to_string())
            }
        }
    }
}

When I consume the iterator by printling out the lines, I dont see the Connection closed message, when I dont consume it, I see the connection closed message. why is that so?

@2002-harshit Apologies, I’ve had this on my list for a LONG time but only finally got around to experimenting with it today.

I think what’s happening here is that when you consume the iterator by printing out the lines, the iterator continues to read lines until it encounters an error or reaches EOF (end of file). Since EOF isn’t reached until the connection is closed from the tester’s side, the program would basically block waiting for more input, hence not getting to the point where the “Connection closed” message is present.

Will mark as closed for now, please let us know if you still need help!

Yeah, thanks a lot for the solution

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.