drogonframework / drogon

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

registerPostHandlingAdvice on OPTION request #2014

Closed Alexufo closed 2 months ago

Alexufo commented 2 months ago

registerPostHandlingAdvice is not solution to add headers for OPTION request.

Example 'drogon/examples/simple_example/main.cc' use registerPostHandlingAdvice to add Access-Control-Allow-Origin header but it will not work for OPTION request.

Is there a better hook for this?

Mis1eader-dev commented 2 months ago

To insecurely resolve all CORS issues, you can echo back everything the client asks for:

drogon::app()
        .registerSyncAdvice([](const HttpRequestPtr& req) -> HttpResponsePtr
        {
            if(req->method() == drogon::HttpMethod::Options)
            {
                auto resp = HttpResponse::newHttpResponse();
                {
                    const auto& val = req->getHeader("Origin");
                    if(!val.empty())
                        resp->addHeader("Access-Control-Allow-Origin", val);
                }
                {
                    const auto& val = req->getHeader("Access-Control-Request-Method");
                    if(!val.empty())
                        resp->addHeader("Access-Control-Allow-Methods", val);
                }
                resp->addHeader("Access-Control-Allow-Credentials", "true");
                {
                    const auto& val = req->getHeader("Access-Control-Request-Headers");
                    if(!val.empty())
                        resp->addHeader("Access-Control-Allow-Headers", val);
                }
                return std::move(resp);
            }
            return {};
        })
        .registerPostHandlingAdvice([](const HttpRequestPtr& req, const HttpResponsePtr& resp) -> void
        {
            {
                const auto& val = req->getHeader("Origin");
                if(!val.empty())
                    resp->addHeader("Access-Control-Allow-Origin", val);
            }
            {
                const auto& val = req->getHeader("Access-Control-Request-Method");
                if(!val.empty())
                    resp->addHeader("Access-Control-Allow-Methods", val);
            }
            resp->addHeader("Access-Control-Allow-Credentials", "true");
            {
                const auto& val = req->getHeader("Access-Control-Request-Headers");
                if(!val.empty())
                    resp->addHeader("Access-Control-Allow-Headers", val);
            }
        })
        .run();
Alexufo commented 2 months ago

Thanks @Mis1eader-dev it works. Is there any reason not to set headers for all OPTIONS POST GET requests (not just OPTIONS) inside registerSyncAdvice?

Mis1eader-dev commented 2 months ago

Options is a preflight, it asks what it can do before actually doing it, that's why we respond separately for OPTION requests

Alexufo commented 2 months ago

@Mis1eader-dev I mean, why not respond to the POST GET in the registerSyncAdvice hook too?

Mis1eader-dev commented 2 months ago

If you do that then none of your API endpoints will be hit and the sync advice ends up responding to every request