【问题标题】:How to get the cookie from a GET response?如何从 GET 响应中获取 cookie?
【发布时间】:2022-02-27 07:30:59
【问题描述】:

我正在编写一个向网站发出 GET 请求并返回响应 cookie 的函数:

extern crate futures;
extern crate hyper;
extern crate tokio_core;

use tokio_core::reactor::Core;
use hyper::Client;
use std::error::Error;
use hyper::header::Cookie;
use futures::future::Future;

fn get_new_cookie() -> Result<String, Box<Error>> {
    println!("Getting cookie...");
    let core = Core::new()?;
    let client = Client::new(&core.handle());
    println!("Created client");

    let uri = "http://www.cnn.com".parse().expect("Cannot parse url");
    println!("Parsed url");
    let response = client.get(uri).wait().expect("Cannot get url.");
    println!("Got response");
    let cookie = response
        .headers()
        .get::<Cookie>()
        .expect("Cannot get cookie");
    println!("Cookie: {}", cookie);

    Ok(cookie)
}

fn main() {
    println!("{:?}", get_new_cookie());
}

这不起作用;它卡在client.get(...) 字符串上。我得到的输出是:

Getting cookie...
Created client
Parsed url

然后什么都没有发生。

我做错了什么以及如何更改它以使其正常工作?

【问题讨论】:

  • 这与 cookie 有什么关系?问题出在let response 行中,与cookie 完全无关。
  • 服务器返回的cookies在Set-Cookie标头中; Cookie 标头用于向服务器发送 cookie 的请求。

标签: http cookies rust hyper


【解决方案1】:

作为Stefan points out,通过调用wait,您将线程置于休眠状态,直到未来完成。但是,该线程需要运行事件循环,因此您刚刚导致了死锁。使用Core::run 更正确。

作为Francis Gagné points out,“Cookie”标头用于将 cookie发送到服务器SetCookie 用于向客户端发送 cookie。它还返回一个包含所有 cookie 的向量:

fn get_new_cookie() -> Result<String, Box<Error>> {
    println!("Getting cookie...");
    let mut core = Core::new()?;

    let client = Client::new(&core.handle());
    println!("Created client");

    let uri = "http://www.cnn.com".parse().expect("Cannot parse url");
    println!("Parsed url");

    let response = core.run(client.get(uri)).expect("Cannot get url.");
    println!("Got response");

    let cookie = response
        .headers()
        .get::<SetCookie>()
        .expect("Cannot get cookie");
    println!("Cookie: {:?}", cookie);

    Ok(cookie.join(","))
}

但是,如果您只需要同步 API,请改用 Reqwest。它建立在 Hyper 之上:

extern crate reqwest;

use std::error::Error;
use reqwest::header::SetCookie;

fn get_new_cookie() -> Result<String, Box<Error>> {
    let response = reqwest::get("http://www.cnn.com")?;

    let cookies = match response.headers().get::<SetCookie>() {
        Some(cookies) => cookies.join(","),
        None => String::new(),
    };

    Ok(cookies)
}

fn main() {
    println!("{:?}", get_new_cookie());
}

【讨论】:

    【解决方案2】:

    documentation for the wait method

    注意:此方法不适合调用事件循环或类似方法 I/O 情况,因为它会阻止事件循环 进度(这会阻塞线程)。这个方法应该只被调用 当保证与此相关的阻塞工作时 未来将由另一个线程完成。

    Future::wait 已经是deprecated in the tokio-reform 分支。

    我建议设计完整的应用程序来处理异步概念(即 get_new_cookie 应该采用 Handle 并返回 Future,而不是分配自己的事件循环)。

    您可以像这样使用Core::run 运行请求:

    let response = core.run(client.get(uri)).expect("Cannot get url.");
    

    【讨论】:

      【解决方案3】:

      reqwest 0.11(可能更早)更新

      get_new_cookie 函数中,我相信从reqwest::Response 检索cookie 的代码sn-p 类似于:

      // returns Option<&HeaderValue>
      
      response.headers().get(http::header::SET_COOKIE)
      

      【讨论】:

        猜你喜欢
        • 2012-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-08
        • 1970-01-01
        • 1970-01-01
        • 2017-01-04
        相关资源
        最近更新 更多