Skip to content

MultipartForm + HTTP2 causes very slow file uploads #3638

@JMLX42

Description

@JMLX42

Your issue may already be reported! Please search on the Actix Web issue tracker before creating one.

Expected Behavior

Sub second latency between the logger and the actual entry in the endpoint handler.

Current Behavior

There is a multi-seconds delay between the tracing span creation and actually entering in the endpoint handler.

Possible Solution

IDK

Update: use HTTP 1.1 (cf #3638 (comment)).

Steps to Reproduce (for bugs)

  1. Add the TracingLogger to the actix-web App
  2. Upload a file using MultipartForm

Context

let app = App::new()
    .wrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly))
    .wrap(tracing_actix_web::TracingLogger::default());
#[derive(ToSchema, MultipartForm)]
pub(crate) struct GlbFileUpload {
    /// The binary glTF (`.glb`) file to import.
    #[schema(format = Binary, content_encoding = "binary", content_media_type = "model/gltf-binary", value_type = String)]
    file: TempFile,
}

#[post("/gltf/import")]
pub async fn import_gltf_file(
    req: HttpRequest,
    db: web::Data<Database>,
    query: web::Query<GltfResourceQueryParameters>,
    MultipartForm(payload): MultipartForm<GlbFileUpload>,
) -> Result<HttpResponse<actix_web::body::BoxBody>, ErrorList> {
    info!(
        "received {:?} ({} bytes) for import",
        payload.file.file_name, payload.file.size,
    );
curl -X 'POST' \
  'https://127.0.0.1:4242/api/gltf/import' \
  -H 'accept: application/vnd.api+json' \
  -H 'Content-Type: multipart/form-data' \
  -F 'file=@/home/jmlx/Downloads/J35Panel7712.vue.scene.glb;type=model/gltf-binary'
2025-05-07T17:36:01.270852Z  INFO HTTP request{http.method=POST http.route=/api/gltf/{gltf_id} http.flavor=2.0 http.scheme=https http.host=127.0.0.1:4242 http.client_ip=127.0.0.1 http.user_agent=curl/8.5.0 http.target=/api/gltf/import otel.name=POST /api/gltf/{gltf_id} otel.kind="server" request_id=0196abd1-94f6-7170-9b4e-003c97b7644d}: tracing_actix_web::root_span_builder: new
2025-05-07T17:36:09.987783Z  INFO HTTP request{http.method=POST http.route=/api/gltf/{gltf_id} http.flavor=2.0 http.scheme=https http.host=127.0.0.1:4242 http.client_ip=127.0.0.1 http.user_agent=curl/8.5.0 http.target=/api/gltf/import otel.name=POST /api/gltf/{gltf_id} otel.kind="server" request_id=0196abd1-94f6-7170-9b4e-003c97b7644d}: gltf_live_api::api::gltf: received Some("J35Panel7712.vue.scene.glb") (30760164 bytes) for import

In this case, 8 seconds for a ~30MB file upload.

Your Environment

  • Rust 1.86.0
  • Actix Web 4.9.0
  • Actix Multipart 0.7.2
  • Storage : Samsung SSD 980 PRO NVME
  • OS : Ubuntu 24.04.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions