Files
backend/common/Cors.cc
T

120 lines
2.9 KiB
C++

#include "common/Cors.h"
#include <drogon/drogon.h>
namespace visione::cors
{
namespace
{
std::vector<std::string> allowedOrigins()
{
auto cfg = drogon::app().getCustomConfig();
std::vector<std::string> origins;
if (cfg.isMember("cors") && cfg["cors"].isObject())
{
auto &c = cfg["cors"];
if (c.isMember("allowed_origin"))
{
auto &v = c["allowed_origin"];
if (v.isArray())
{
for (const auto &el : v)
{
if (el.isString())
origins.emplace_back(el.asString());
}
}
else if (v.isString())
{
origins.emplace_back(v.asString());
}
}
}
if (origins.empty())
origins.emplace_back("http://localhost:5173");
return origins;
}
bool isAllowed(const drogon::HttpRequestPtr &request)
{
auto origin = request->getHeader("Origin");
if (origin.empty())
return false;
auto origins = allowedOrigins();
for (const auto &o : origins)
{
if (o == "*" || o == origin)
return true;
}
return false;
}
void addHeaders(const drogon::HttpRequestPtr &request,
const drogon::HttpResponsePtr &response)
{
auto origin = request->getHeader("Origin");
if (origin.empty())
return;
auto origins = allowedOrigins();
bool allowAll = false;
bool matched = false;
for (const auto &o : origins)
{
if (o == "*")
{
allowAll = true;
break;
}
if (o == origin)
{
matched = true;
break;
}
}
if (!allowAll && !matched)
return;
if (allowAll)
response->addHeader("Access-Control-Allow-Origin", "*");
else
response->addHeader("Access-Control-Allow-Origin", origin);
response->addHeader("Access-Control-Allow-Credentials", "true");
response->addHeader("Access-Control-Allow-Methods",
"GET,POST,PATCH,DELETE,OPTIONS");
response->addHeader("Access-Control-Allow-Headers",
"Authorization,Content-Type");
response->addHeader("Vary", "Origin");
}
} // namespace
void configure()
{
drogon::app().registerSyncAdvice(
[](const drogon::HttpRequestPtr &request) -> drogon::HttpResponsePtr {
if (request->method() != drogon::Options)
{
return nullptr;
}
auto response = drogon::HttpResponse::newHttpResponse();
response->setStatusCode(drogon::k204NoContent);
addHeaders(request, response);
return response;
});
drogon::app().registerPostHandlingAdvice(
[](const drogon::HttpRequestPtr &request,
const drogon::HttpResponsePtr &response) {
addHeaders(request, response);
});
}
} // namespace visione::cors