Files
2026-06-30 17:49:51 +08:00

182 lines
3.8 KiB
C++

#include "CORSConfig.h"
#include <map>
#include <vector>
#include <sstream>
#include "Global.h"
CORSConfig GlobalCORSConfig;
CORSConfig::CORSConfig()
{
max_age = 86400;
allow_cookie = false;
validate_urls = {};
validate_hosts = {};
validate_methods = { "GET", "POST", "OPTIONS" };
validate_headers =
{
"Accept",
"Accept-Language",
"Content-Language",
"Content-Type",
"Authorization",
"X-Requested-With",
"X-CSRF-Token",
"X-Client-Version",
"X-App-Id",
"X-Request-ID"
};
}
int CORSConfig::GetMaxAge() const
{
return max_age;
}
bool CORSConfig::AllowCookie() const
{
return allow_cookie;
}
std::string CORSConfig::GetValidateMethods() const
{
if (validate_methods.empty())
return std::string();
std::ostringstream oss;
size_t index = 0;
for (const auto& method : validate_methods)
{
if (index++ > 0)
oss << ", ";
oss << uns::tools::ToUpper(method); // 统一大写方法名
}
return oss.str();
}
bool CORSConfig::UrlValidate(const std::string& url) const
{
return (validate_urls.find(url) != validate_urls.end());
}
bool CORSConfig::HostValidate(const std::string& host) const
{
return (validate_hosts.find(host) != validate_hosts.end());
}
bool CORSConfig::IsMethodAllowed(const std::string method) const
{
return (validate_methods.find(method) != validate_methods.end());
}
std::string CORSConfig::GetValidateHeaders(const std::set<std::string>& headers) const
{
// build map from lowercase(validate_headers) => original form (preserve casing)
std::map<std::string, std::string> lowerToOriginal;
for (const auto& h : validate_headers)
lowerToOriginal[uns::tools::ToLower(h)] = h;
std::vector<std::string> allowedOut;
if (headers.empty())
{
// 返回服务端全部允许的头(保持 validate_headers 中的原始展示形式)
for (const auto& kv : lowerToOriginal)
allowedOut.push_back(kv.second);
}
else
{
// 交集比较(headers 已经是小写的—为了健壮性,再转换一次)
for (const auto& reqLower : headers)
{
std::string reqNorm = uns::tools::ToLower(reqLower);
auto it = lowerToOriginal.find(reqNorm);
if (it != lowerToOriginal.end())
allowedOut.push_back(it->second); // 使用原始展示形式
}
// 如果客户端请求了头(headers 非空)但交集为空,返回空字符串
}
if (allowedOut.empty())
return std::string();
// join with ", "
std::ostringstream oss;
for (size_t i = 0; i < allowedOut.size(); ++i)
{
if (i)
oss << ", ";
oss << allowedOut[i];
}
return oss.str();
}
void CORSConfig::SetMaxAge(int max_age)
{
this->max_age = max_age;
}
void CORSConfig::SetAllowCookie(bool allow)
{
allow_cookie = allow;
}
void CORSConfig::ClearValidateUrls()
{
validate_urls.clear();
}
void CORSConfig::ClearValidateHosts()
{
validate_hosts.clear();
}
void CORSConfig::ClearValidateMethods()
{
validate_methods.clear();
}
void CORSConfig::ClearValidateHeaders()
{
validate_headers.clear();
}
void CORSConfig::AddValidateUrl(const std::string& url)
{
validate_urls.insert(url);
}
void CORSConfig::AddValidateHost(const std::string& host)
{
validate_hosts.insert(host);
}
void CORSConfig::AddValidateMethod(const std::string& method)
{
validate_methods.insert(uns::tools::ToUpper(method));
}
void CORSConfig::AddValidateHeader(const std::string& header)
{
validate_headers.insert(header);
}
void CORSConfig::AddValidateUrls(const std::set<std::string>& urls)
{
for(const auto& url : urls)
validate_urls.insert(url);
}
void CORSConfig::AddValidateHosts(const std::set<std::string>& hosts)
{
for(const auto& host : hosts)
validate_hosts.insert(host);
}
void CORSConfig::AddValidateMethods(const std::set<std::string>& methods)
{
for(const auto& method : methods)
validate_methods.insert(method);
}
void CORSConfig::AddValidateHeaders(const std::set<std::string>& headers)
{
for(const auto& header : headers)
validate_headers.insert(header);
}