You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
actix-multipart's file fields should yield all the bytes streamed until it's done
Current Behavior
actix-multipart's file fields gets stuck awaiting data forever
Possible Solution
I don't have a possible solution, sorry
Steps to Reproduce
Running this code should be enough to reproduce the bug!
use std::{fs, io::Write};use actix_multipart::{Field,Multipart};use actix_web::{web,App,HttpResponse,HttpServer,Responder};use futures_util::stream::StreamExt;#[actix_web::main]asyncfnmain() -> Result<(), actix_web::Error>{
fs::create_dir_all("./uploads").expect("cannot create profile pics directory");HttpServer::new(move || App::new().route("/upload", web::post().to(upload))).bind("127.0.0.1:8000")?
.run().await?;Ok(())}// If we change this to `mut payload: Multipart`...asyncfnupload(payload:Multipart) -> implResponder{// ...and here to &mut payload, it works.let photo = get_multipart_field("photo", payload).await;ifletSome(mut field) = photo {letmut file = web::block(|| fs::File::create("./uploads/test")).await.unwrap();// Here is where it gets stuckprintln!("Before getting data");whileletSome(chunk) = field.next().await{println!("This never prints!");let data = chunk.unwrap();
file = web::block(move || file.write_all(&data).map(|_| file)).await.unwrap();}HttpResponse::Ok()}else{HttpResponse::BadRequest()}}asyncfnget_multipart_field(name:&str,mutpayload:Multipart,// If we change this to `payload: &mut Multipart`, it works) -> Option<Field>{whileletSome(field) = payload.next().await{let field = field.unwrap();ifletSome(content_disposition) = field.content_disposition(){match content_disposition.get_name(){Some(field_name)if name == field_name => returnSome(field),
_ => continue,}}}None}
You can hit the endpoint with this curl:
curl -i -X POST -F photo=@"<PATH_TO_A_FILE>" http://127.0.0.1:8000/upload
Context
I was just testing how to upload a file using actix-multipart
Environment
OS: Ubuntu 20.04.03
Rust Version: rustc 1.56.0 (09c42c458 2021-10-18)
Actix Web Version: 3.3.2
Actix Multipart version: 0.3.0
futures-util: 0.3.17
The text was updated successfully, but these errors were encountered:
From a quick glance: I don't think the problem is with moving payload. I think the problem is with dropping payload prematurely.
When you move payload into the function, it drops when the function ends, and then you're trying to extract chunks from the field stream after payload is gone already.
It's not intuitive that the field stream is tied to the payload stream in this way
The original code intended to handle this case by failing immediately instead of hanging. #2463
I won't argue for this behavior, but this is the eaziest way to be fixed until we figure out the proper way for synchronizing Multipart and Field and whether we want to allow them to be spawned to separate tasks.
Expected Behavior
actix-multipart's file fields should yield all the bytes streamed until it's done
Current Behavior
actix-multipart's file fields gets stuck awaiting data forever
Possible Solution
I don't have a possible solution, sorry
Steps to Reproduce
Running this code should be enough to reproduce the bug!
You can hit the endpoint with this curl:
Context
I was just testing how to upload a file using actix-multipart
Environment
The text was updated successfully, but these errors were encountered: