0

I just started writing in Rust and I am writing a small program to learn Rust and the package Reqwest.

Here's my little program. I don't understand why changing from HashMap<&str, &str> to HashMap<String, String> can make it work whilst cookie still only lives within the scope? I've commented my doubts along the code as well.

use reqwest::cookie::Jar;
use reqwest::{Client, Url};
use std::sync::Arc;
use std::collections::HashMap;

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let jar = Jar::default();
    let raw_url = "https://www.google.com";

    let url = Url::parse("https://www.google.com").unwrap();
    jar.add_cookie_str("session=1", &url);

    let jar = Arc::new(jar);
    let client_builder = Client::builder();

    let client = client_builder
                   .cookie_provider(Arc::clone(&jar))
                   .build()?;

    let response = client.get(raw_url).send().await?;

    let headers: &HeadersMap = response.headers();

    let cookies: Impl Iterator<Item=Cookie>+Sized = response.cookies();

    // let mut cookie_map = HashMap::<String, String>::new(); // this would work;

    let mut cookie_map = HashMap::<&str, &str>::new(); // impl<'a> Cookie<'a>

    let mut header_map = HashMap::<&str, &str>::new(); // live as long as the programme

    for cookie in cookies { // declared borrowed value here, hence the lifetime kicks in
         // Error: cookie does not live long enough
         cookie_map.insert(cookie.name(), cookie.value());

         // cookie_map.insert(cookie.name().to_string(), cookie.value().to_string());
         // with `to_string` we have taken ownership of the value; is this why it's working?
    }
    // cookie dropped while still borrowed here;
    // kv pairs are both borrowed values that have a lifetime `'a` which ends here
    // and cookie_map apparently continues to exist, hence the error (this is my guess)
    

    for (k, v) in headers.iter() {
         match v.to_str() {
             Ok(val) => header_map.insert(k.as_str(), val),
             Err(_) => panic!()
         };
    }
    

    for (hk, kv) in header_map {
         println!("header name is {}, header value is {}", hk, kv);
    }

    Ok(())
}

Here's the cargo.toml:

[package]
name = "tester"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[[bin]]
name = "tester"
test = false
bench = false

[dependencies]
reqwest = { version = "0.11", features = ["blocking", "json", "cookies"] }
tokio = { version = "1", features = ["full"] }
futures = "0.3"
reqwest_cookie_store = "0.7.0"

cargo check error log is provided here:


error[E0597]: `cookie` does not live long enough
  --> src/tools/fetcher.rs:32:32
   |
31 |          for cookie in cookies {
   |              ------ binding `cookie` declared here
32 |              cookie_map.insert(cookie.name(), cookie.value());
   |              ----------        ^^^^^^ borrowed value does not live long enough
   |              |
   |              borrow later used here
33 |          }
   |          - `cookie` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.
error: could not compile `data_fetcher` (bin "data_fetcher") due to 1 previous error


7
  • I am well aware you included the error in the comment. IMO it is hard to read this way, which is why I politely asked for the error from cargo check. As @cafce25 said, supplying a comment with a downvote is not required, for reasons explained in the Q&A they linked. I do try to leave a comment when I downvote (most of the times). And for the record, I am not the downvoter here. I don't think this should matter for you thought, nor I think you should take a single downvote into heart (or really, any number of downvotes). A single downvote means one user has found your question to... Commented Jun 20, 2024 at 13:25
  • ...to "not show any research effort; unclear or not useful" as explained in the tooltip. Commented Jun 20, 2024 at 13:26
  • Alternative solution has been provided as per comment in the code snippet it came from research and trials. Reqwest API quoted for cookie showed more evidence. Functional example has been provided, I don't see how it's unclear or not useful. @ChayimFriedman But thank you for coming back for a reason. Commented Jun 20, 2024 at 13:32
  • Me neither, I even gave an upvote. That's why I said that one person has found your question to be such. Commented Jun 20, 2024 at 15:22
  • @ChayimFriedman thanks for your explanation and I shall give my apologies to you as it's surely overdue. We've been on SO for sometimes (9 and 7 years), at times, especially last two years there's a rising trend of just downvoting people without a valid reason; whenever I see one I normally peruse the question and upvote it if it's due. Few years back people were practising their SO rights in a much more gentle and nicer way. In reminiscence of that, I was a bit agitated, admittedly. Thanks that you didn't take it heart. Commented Jun 20, 2024 at 17:02

1 Answer 1

2

cookie only exists during the duration of one iteration of the loop. &str is a reference to a string, so the value referenced must live at least as long as the HashMap the reference is in. But since cookie is destroyed after the iteration, the value is lost.

The solution is to take ownership of the &str. That's what you did by changing the type to String.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you; I guessed the same as you have explained here. What I am still in doubt is, isn't cookie.name() still only exists for 'a, which is the for loop here? Am I correct to say by doing to_string(), the cookie.name()'s value is actually owned now by my programme and no longer borrowed only from cookie?
The lifetime of the reference returned by cookie.name() is most likely the lifetime of the cookie itself. The lifetime of cookie is difficult to pinpoint from this code snippet, as the Iterator might be pulling the value from an existing array, or constructing the cookie objects on-the-fly. The to_string() function takes the reference and clones the data into a new String so you can own it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.