Я пытаюсь сделать POST HTTP-запрос с помощью библиотеки Hyper, а затем записывать в него данные, пока не закрою его (из нескольких функций/потоков). В документации я нашел, что для этого можно использовать Body::channel(), но я использую его неправильно, так как могу записать в канал только один раз. Я не нашел ни одного примера, может кто-нибудь подскажет мне правильное направление?

let (mut sender, body) = Body::channel();

let request = Request::builder()
    .method(Method::POST)
    .uri("http://localhost:3000/")
    .header("content-type", "text")
    .body(body)
    .unwrap();

let client = Client::new();
let response = client.request(request);

//Does get sent
println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test\n")).await);
//Stuck on this one
println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test2\n")).await);
//Debug print
println!("{:?}", response.await);

Makalone LOgman

Ответов: 1

Ответы (1)

Вам нужно обернуть send_data() строки в tokio::spawn(async move { ... });.

Проблема в том, что Body/Sender имеет размер буфера только 1. Поэтому второй вызов send_data() заставляет его ожидать (внутренне), пока Sender не будет готов. Именно это впоследствии приводит к "застреванию".

Это решается с помощью tokio::spawn(), поскольку это наконец-то позволяет дождаться создания ResponseFuture, что приводит к выполнению запроса.

let (sender, body) = Body::channel();

let request = Request::builder()
    .method(Method::POST)
    .uri("http://localhost:3000/")
    .header("content-type", "text")
    .body(body)
    .unwrap();

let client = Client::new();

let response = client.request(request);

tokio::spawn(async move {
    let mut sender = sender;

    println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test\n")).await);
    println!("Body: {:?}", sender.send_data(hyper::body::Bytes::from("test2\n")).await);
});

println!("{:?}", response.await);

Размер буфера не упоминается в документации (насколько я знаю). Однако вы можете выяснить это, проверив источник, связанный с Body::channel(), где видно, что он строит MPSC, используя futures_channel::mpsc::channel(0). В документации упоминается, что размер буфера должен быть buffer + num-senders, что в нашем случае будет 0 + 1.

2022 WebDevInsider