drogonframework / drogon

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

CORS issue when Get static file 在获取静态文件时遇到了CORS策略拦截 #2183

Closed MiQter closed 1 month ago

MiQter commented 1 month ago

I have added support for the obj static file format in the main.cc file, but when I retrieve the obj file using a Get Url request, the request is blocked by the CORS policy. How can I resolve this issue? 我在main.cc文件中增加了对obj静态文件格式的支持,但是通过Get方式的url请求获取obj文件,该请求被CORS策略拦截,请问应该如何解决?

#include <drogon/drogon.h>

int main() {
    drogon::app().addListener("0.0.0.0", 5556);

    drogon::app().setFileTypes({"gif",
                                  "png",
                                  "jpg",
                                  "js",
                                  "css",
                                  "html",
                                  "ico",
                                  "swf",
                                  "xap",
                                  "apk",
                                  "cur",
                                  "xml",
                                  "obj"});

    drogon::app()
            .registerSyncAdvice([](const drogon::HttpRequestPtr& req) -> drogon::HttpResponsePtr
                                {
                                    if(req->method() == drogon::HttpMethod::Options)
                                    {
                                        auto resp = drogon::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 drogon::HttpRequestPtr& req, const drogon::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();

    return 0;
}
an-tao commented 1 month ago

试试把MiddleWare配置到需要支持CORS的location上,配置文件里有locations配置项

MiQter commented 1 month ago

Can you explain in detail which configuration item of location should be updated to MiddleWare? 能详细说一下,将MiddleWare更新到location的哪个配置项吗?

HttpAppFramework.h

    /**
     * @brief Add a location of static files for GET requests.
     *
     * @param uriPrefix The URI prefix of the location prefixed with "/"
     * @param defaultContentType The default content type of the static files
     * without an extension.
     * @param alias The location in file system, if it is prefixed with "/", it
     * presents an absolute path, otherwise it presents a relative path to the
     * document_root path.
     * @param isCaseSensitive
     * @param allowAll If it is set to false, only static files with a valid
     * extension can be accessed.
     * @param isRecursive If it is set to false, files in sub directories can't
     * be accessed.
     * @param filters The list of filters which acting on the location.
     * @return HttpAppFramework&
     */
    virtual HttpAppFramework &addALocation(
        const std::string &uriPrefix,
        const std::string &defaultContentType = "",
        const std::string &alias = "",
        bool isCaseSensitive = false,
        bool allowAll = true,
        bool isRecursive = true,
        const std::vector<std::string> &filters = {}) = 0;

config.json

        "locations": [
            {
                //uri_prefix: The URI prefix of the location prefixed with "/", the default value is "" that disables the location.
                //"uri_prefix": "/.well-known/acme-challenge/",
                //default_content_type: The default content type of the static files without
                //an extension. empty string by default.
                "default_content_type": "text/plain",
                //alias: The location in file system, if it is prefixed with "/", it 
                //presents an absolute path, otherwise it presents a relative path to 
                //the document_root path. 
                //The default value is "" which means use the document root path as the location base path.
                "alias": "",
                //is_case_sensitive: indicates whether the URI prefix is case sensitive.
                "is_case_sensitive": false,
                //allow_all: true by default. If it is set to false, only static files with a valid extension can be accessed.
                "allow_all": true,
                //is_recursive: true by default. If it is set to false, files in sub directories can't be accessed.
                "is_recursive": true,
                //filters: string array, the filters applied to the location.
                "filters": []
            }
        ],
an-tao commented 1 month ago

放到filters里,middleWare是对filter的扩展,增加了后处理逻辑,这里沿用了原来的配置项。

MiQter commented 1 month ago

放到filters里,middleWare是对filter的扩展,增加了后处理逻辑,这里沿用了原来的配置项。

The problem has been solved according to the method you said. During the resolution process, it was discovered that drogon.1.9.1 did not have the HttpMiddleware class. After updating to the latest version of drogon, this issue was resolved. The following is the resolved code for future use. 按照你说的方法,问题已经解决。 在解决过程中,发现drogon.1.9.1没有HttpMiddleware这个类,更新了drogon的最新版本后,这个问题解决了。 以下为解决的代码,供后来人使用。

api_v1_BaseMiddleWare.h

/**
 *
 *  api_v1_baseMiddleWare.h
 *
 */

#pragma once

#include <drogon/HttpMiddleware.h>

using namespace drogon;
namespace api {
    namespace v1 {

        class BaseMiddleWare : public HttpMiddleware<BaseMiddleWare> {
        public:
            BaseMiddleWare() {}

            void invoke(const HttpRequestPtr &req,
                        MiddlewareNextCallback &&nextCb,
                        MiddlewareCallback &&mcb) override;
        };

    }
}

api_v1_BaseMiddleWare.cc

/**
 *
 *  api_v1_baseMiddleWare.cc
 *
 */

#include "api_v1_BaseMiddleWare.h"

using namespace drogon;
using namespace api::v1;

void BaseMiddleWare::invoke(const HttpRequestPtr &req,
                            MiddlewareNextCallback &&nextCb,
                            MiddlewareCallback &&mcb) {
    const auto &origin = req->getHeader("Origin");
    const auto &method = req->getHeader("Access-Control-Request-Method");
    const auto &headers = req->getHeader("Access-Control-Request-Headers");
    nextCb([mcb = std::move(mcb), origin, method, headers](const HttpResponsePtr &resp) {
        if (!origin.empty()) {
            resp->addHeader("Access-Control-Allow-Origin", origin);
        }
        if (!method.empty()) {
            resp->addHeader("Access-Control-Allow-Methods", method);
        }
        resp->addHeader("Access-Control-Allow-Credentials", "true");
        if (!headers.empty()) {
            resp->addHeader("Access-Control-Allow-Headers", headers);
        }
        mcb(resp);
    });
}

Add the following statement in main.cc 在main.cc中添加以下语句

    drogon::app().addALocation("","text/plain","",false,true,true,{"api::v1::BaseMiddleWare"});
MiQter commented 1 month ago

放到filters里,middleWare是对filter的扩展,增加了后处理逻辑,这里沿用了原来的配置项。

Thank you so much for your prompt and helpful response! Your insight has resolved my issue and I truly appreciate your time and effort in assisting me. 非常感谢您的迅速且有用的回复!您的见解解决了我的问题,我真心感激您花时间和精力来帮助我。