drogonframework / drogon

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows
MIT License
11.45k stars 1.1k forks source link

MultiPartParser not detecting uploaded files #1974

Closed GladBarsan closed 2 weeks ago

GladBarsan commented 6 months ago

Description: I am experiencing an issue with the Drogon web framework where the MultiPartParser is not getting any uploaded files in my POST request handler. I have installed Drogon from the git repository on February 16, 2024, with the last pulled commit being 88d06684. I am running the code on Linux Ubuntu 22.04.2.

Here is a simplified version of my code:

void POSHttpController::set_picture(const drogon::HttpRequestPtr& req, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
    MultiPartParser fileUpload;
    int parseResult = fileUpload.parse(req);
    if (parseResult != 0) {
        LOG_ERROR << "Failed to parse multipart request. Error code: " << parseResult;
        auto resp = HttpResponse::newHttpResponse();
        resp->setBody("Failed to parse multipart request");
        resp->setStatusCode(k400BadRequest);
        callback(resp);
        return;
    }

    auto file_map = fileUpload.getFilesMap();
    LOG_DEBUG << "File map size: " << file_map.size(); // Always 0

    auto files = fileUpload.getFiles();
    if (files.size() != 1) {
        LOG_ERROR << "Invalid number of files. Expected 1, got " << files.size(); // Got 0
        auto resp = HttpResponse::newHttpResponse();
        resp->setBody("Must only be one file");
        resp->setStatusCode(k403Forbidden);
        callback(resp);
        return;
    }

    // ...
}

The parse() function returns 0, indicating a successful parse, but both getFilesMap() and getFiles() return empty collections. I have verified that the request contains a file, but it seems that the MultiPartParser is not detecting it. I should also specify that this same code does work with an older version of drogon that I have on another machine (even with the same file/request). I would greatly appreciate any help or suggestions on how to resolve this issue. Please let me know if you need any additional information.

Thank you in advance!

an-tao commented 6 months ago

Could you please share your client code so I can reproduce this issue locally?

GladBarsan commented 6 months ago

I was just using Postman for testing. image And these are the headers image Most are auto calculated.

And yes, this exact request works fine on the older version, but the new one responds with "Must be only one file"

an-tao commented 6 months ago

I did some tests with your controller code and postman, but I can't reproduce this issue, it works fine in my local environment.

GladBarsan commented 6 months ago

After multiple tries (even reinstalling drogon) I managed to narrow it down. It only happens for files larger than 64kb (when they are over the default client_max_memory_body_size). So it appears it only goes wrong when the request body is put in the temp file. I tested this by removing the limit, and the files were detected. Hope this helps!

an-tao commented 6 months ago

I works fine when I tried to upload a file of 300k bytes. Please check if your application has write permission to the temporary files folder.