添加项目文件。

This commit is contained in:
UnknownObject
2026-06-30 17:46:34 +08:00
parent 415124601e
commit d7ce0fe00a
75 changed files with 9723 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
#include "CORSProcessor.h"
#include "ServerLogger.h"
#include "CORSConfig.h"
#include "UNSResponseBuilder.h"
// ----- 辅助函数(文件作用域) -----
static inline std::string Trim(const std::string& s)
{
size_t start = 0;
while ((start < s.size()) && std::isspace(static_cast<unsigned char>(s[start])))
++start;
if (start == s.size())
return "";
size_t end = s.size() - 1;
while ((end > start) && std::isspace(static_cast<unsigned char>(s[end])))
--end;
return s.substr(start, end - start + 1);
}
static inline std::vector<std::string> SplitByComma(const std::string& raw)
{
std::vector<std::string> parts;
std::istringstream ss(raw);
std::string token;
while (std::getline(ss, token, ','))
parts.push_back(token);
return parts;
}
// 1) 解析请求头(Access-Control-Request-Headers)
// 返回小写形式的集合(用于比较/交集)
std::set<std::string> CORSProcessor::ParseHeaderList(const std::string& raw_headers)
{
std::set<std::string> out;
if (raw_headers.empty())
return out;
auto parts = SplitByComma(raw_headers);
for (const auto& p : parts)
{
std::string t = Trim(p);
if (t.empty())
continue;
out.insert(uns::tools::ToLower(t)); // 规范化为小写用于比较
}
return out;
}
// 2) 解析请求方法字符串(Access-Control-Request-Method 或逗号分隔的 Methods)
// 返回大写形式的集合(用于比较)
std::set<std::string> CORSProcessor::ParseMethodList(const std::string& raw_headers)
{
std::set<std::string> out;
if (raw_headers.empty())
return out;
auto parts = SplitByComma(raw_headers);
for (const auto& p : parts)
{
std::string t = Trim(p);
if (t.empty())
continue;
out.insert(uns::tools::ToUpper(t));
}
return out;
}
uns::ResponsePtr CORSProcessor::Processor(uns::RequestPtr request)
{
if(request->GetMethod() != "OPTIONS")
return uns::ResponseBuilder().MethodNotAllowed().EmptyBody()();
SCLOG_INFO("OPTIONS Request Catched!");
if((!request->HasHeader(uns::cors::reqh_acrm)) || (!request->HasHeader(uns::cors::reqh_o)))
return uns::ResponseBuilder().BadRequest().EmptyBody()();
std::string origin = Trim(request->GetHeader(uns::cors::reqh_o));
std::string acrm = Trim(request->GetHeader(uns::cors::reqh_acrm));
std::string acrh = request->HasHeader(uns::cors::reqh_acrh) ? Trim(request->GetHeader(uns::cors::reqh_acrh)) : std::string();
std::string host = request->HasHeader("Host") ? request->GetHeader("Host") : "";
if ((!host.empty()) && (!GlobalCORSConfig.HostValidate(host)))
{
SCLOG_WARNING("Rejected by Host check: %s", host.c_str());
return uns::ResponseBuilder().Forbidden().EmptyBody()();
}
if(!GlobalCORSConfig.UrlValidate(origin))
{
SCLOG_WARNING("Invalid CORS Origin: %s", origin.c_str());
return uns::ResponseBuilder().Forbidden().EmptyBody()();
}
auto acrm_values = ParseMethodList(acrm);
if (acrm_values.empty())
{
SCLOG_WARNING("Empty Access-Control-Request-Method");
return uns::ResponseBuilder().BadRequest().EmptyBody()();
}
for(const auto& method : acrm_values)
if(!GlobalCORSConfig.IsMethodAllowed(method))
{
SCLOG_WARNING("Invalid CORS Method: %s (All Methods: %d)", method.c_str(), acrm.c_str());
return uns::ResponseBuilder().NotAcceptable().EmptyBody()();
}
auto acrh_values = acrh.empty() ? std::set<std::string>() : ParseHeaderList(acrh);
if (!acrh_values.empty())
{
const size_t MAX_HDR_COUNT = 50;
const size_t MAX_HDR_TOTAL_LEN = 4096; // 可调整
if ((acrh_values.size() > MAX_HDR_COUNT) || (acrh.size() > MAX_HDR_TOTAL_LEN))
{
SCLOG_WARNING("ACRH too large or too many entries");
return uns::ResponseBuilder().BadRequest().EmptyBody()();
}
}
auto valid_headers = GlobalCORSConfig.GetValidateHeaders(acrh_values);
if((!acrh_values.empty()) && valid_headers.empty())
{
SCLOG_WARNING("Invalid CORS Header(s): %s", acrh.c_str());
return uns::ResponseBuilder().NotAcceptable().EmptyBody()();
}
std::string allow_methods_value = GlobalCORSConfig.GetValidateMethods();
if (allow_methods_value.empty())
{
SCLOG_WARNING("No allowed methods configured");
return uns::ResponseBuilder().Forbidden().EmptyBody()();
}
SCLOG_INFO("CORS preflight allow origin=%s methods=%s headers=%s cred=%d", origin.c_str(), allow_methods_value.c_str(), valid_headers.c_str(), GlobalCORSConfig.AllowCookie() ? 1 : 0);
return uns::ResponseBuilder().CORS_Full(origin, acrh_values).NoContent().EmptyBody()();
}
std::string CORSProcessor::UrlRegex()
{
return R"(/[\s\S]*)";
}
std::shared_ptr<CORSProcessor> CORSProcessor::SharedPtr()
{
return std::make_shared<CORSProcessor>();
}