I have this method:
fn parse_http_request_headers<'b>(sp: &'b mut std::str::Split<&str>) -> HashMap<String, String> {
let mut headers: HashMap<String, String> = HashMap::new();
let mut iter = sp.peekable();
while iter.peek() != None {
let next = iter.next();
if let Some(value_to_parse) = next {
let parts = value_to_parse.split(": ").collect::<Vec<&str>>();
let key = parts.get(0);
if parts.len() == 2 {
headers.insert(
(*key.expect(&format!("Error getting the header definition: {:?}", &key)))
.to_string(),
(*parts.get(1)
.expect(&format!("Error getting the header value from: {:?}", &parts)))
.to_string()
);
}
} else { iter.next(); }
}
headers
}
that I refactored for curiosity about playing with the Interior mutability pattern
, to try to solve some doubts about struct's fields that contains references.
But, ok, let's go with the code:
fn parse_http_request_headers<'b>(sp: Rc<RefCell<&'b mut std::str::Split<&str>>>) -> HashMap<String, String> {
let mut headers: HashMap<String, String> = HashMap::new();
let mut borrow = sp.borrow_mut(); // let binding
let mut iter = borrow.peekable();
while iter.peek() != None {
let next = iter.next();
if let Some(value_to_parse) = next {
let parts = value_to_parse.split(": ").collect::<Vec<&str>>();
let key = parts.get(0);
if parts.len() == 2 {
headers.insert(
(*key.expect(&format!("Error getting the header definition: {:?}", &key)))
.to_string(),
(*parts.get(1)
.expect(&format!("Error getting the header value from: {:?}", &parts)))
.to_string()
);
}
} else { iter.next(); }
}
headers
}
But, for my surprise, there's no iterations over the peekable peeked: None
.
Why is causing this?
The first version works perfect parsing the http headers, this is the output:
HttpRequest { verb: GET, uri: Uri { uri: "/" }, http_version: V1_1, headers: {"Sec-Fetch-Mode": "navigate", "Connection": "keep-alive", "DNT": "1", "Sec-Fetch-Site": "none", "Host": "127.0.0.1:7878", "Sec-GPC": "1", "Sec-Fetch-User": "?1", "Upgrade-Insecure-Requests": "1", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br", "Sec-Fetch-Dest": "document"}, body: None }
The calling code:
let rc: Rc<RefCell<&mut Split<&str>>> = Rc::new(RefCell::new(sp));
let (verb, uri, version) = Self::parse_verb_uri_version(Rc::clone(&rc));
let body = Self::parse_http_request_body(Rc::clone(&rc).borrow_mut().last().unwrap());
let headers = Self::parse_http_request_headers(Rc::clone(&rc));
where sp
:
sp: &'a mut Split<&'a str>
Thanks.
You use .last()
in the proceeding line which will consume all elements from the iterator leaving nothing behind to iterate in parse_http_request_headers()
.