2017-12-17 8 views
0

Ich schreibe eine Funktion, die eine GET-Anforderung an eine Website macht und gibt die Antwort Cookie:Wie bekomme ich den Cookie von einer GET-Antwort?

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()); 
} 

Dies funktioniert nicht; es ist auf der client.get(...) Zeichenfolge fest. Die Ausgabe, die ich bekomme, ist:

und danach passiert nichts.

Was mache ich falsch und wie kann ich es ändern, damit es funktioniert?

+0

Wie ist das im Zusammenhang mit Cookies? Das Problem liegt in der Zeile "Antwort loslassen", die überhaupt nicht mit Cookies verknüpft ist. –

+0

Die vom Server zurückgegebenen Cookies befinden sich im Header "Set-Cookie". Der 'Cookie'-Header wird in Anfragen verwendet, um Cookies an den Server zu senden. –

Antwort

2

Als Stefan points out, durch wait aufrufen, müssen Sie den Faden setzen zu schlafen, bis die Zukunft abgeschlossen hat. Dieser Thread muss jedoch die Ereignisschleife ausführen, sodass Sie gerade einen Deadlock verursacht haben. Die Verwendung von Core::run ist richtiger.

Als Francis Gagné points out wird die "Cookie" -Kopfzeile verwendet, um einen Cookie an den Server zu senden. SetCookie wird verwendet, um einen Cookie an den Client zu senden. Es gibt auch einen Vektor aller Cookies zusammen:

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(",")) 
} 

Wenn Sie jedoch nur eine synchrone API wollen, statt Reqwest verwenden. Es ist auf Hyper erstellt:

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

Siehe documentation for the wait method:

Hinweis: Diese Methode ist nicht geeignet für das Event zu nennen Schleifen oder ähnliche E/A-Situationen, weil es aus machen Fortschritt die Ereignisschleife verhindern (dies blockiert die Faden). Diese Methode sollte nur aufgerufen werden, wenn sichergestellt ist, dass die mit dieser Zukunft verbundene Sperrarbeit von einem anderen Thread abgeschlossen wird.

Future::wait ist bereits deprecated in the tokio-reform Zweig.

Ich würde empfehlen, die vollständige Anwendung zu entwerfen, um mit async Konzepte zu behandeln (d. H. get_new_cookie sollte eine Handle nehmen und eine Future zurückgeben, keine eigene Ereignisschleife zuzuteilen).

Sie konnten die Anfrage mit Core::run wie folgt ausführen:

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