change how origin header is treated
Now check whether the origin is in allowed_origins table, and if not check allow_all_origins config parameter. While here: - add are_cors_preflight_requests_available - if true then preflight requests are available (default false)
This commit is contained in:
parent
05ecac8426
commit
6138497fe0
|
@ -357,8 +357,9 @@ void Config::AssignValues()
|
|||
|
||||
request_queue_job_limit = Size(L"request_queue_job_limit", 1024);
|
||||
|
||||
allow_all_cors_origins = Bool(L"allow_all_cors_origins", false);
|
||||
ListText(L"allowed_cors_origins", allowed_cors_origins);
|
||||
ListText(L"allowed_origins", allowed_origins);
|
||||
allow_all_origins = Bool(L"allow_all_origins", true);
|
||||
are_cors_preflight_requests_available = Bool(L"are_cors_preflight_requests_available", false);
|
||||
ListText(L"access_control_expose_headers", access_control_expose_headers);
|
||||
access_control_allow_credentials = Bool(L"access_control_allow_credentials", false);
|
||||
}
|
||||
|
|
|
@ -1002,18 +1002,21 @@ public:
|
|||
// if the limit is reached then the http status 503 Service Unavailable is returned
|
||||
size_t request_queue_job_limit;
|
||||
|
||||
// whether or not all origins are allowed in cors requests
|
||||
// default: false;
|
||||
// if false then we check allowed_cors_origins table to check whether the origin is available (origin is sent in Origin header),
|
||||
// if allow_all_cors_origins is false and allowed_cors_origins is empty then by default we do not allow cors requests
|
||||
// (but you can still allow it in your function/controller by overriding IsCorsOriginAvailable(...) method)
|
||||
bool allow_all_cors_origins;
|
||||
|
||||
// list of allowed origins in cors requests
|
||||
// can be set per controller in a method: virtual bool FunctionBase::IsCorsOriginAvailable(const std::wstring & origin_url)
|
||||
// used only if allow_all_cors_origins is false
|
||||
// can be set per controller in a method: virtual bool FunctionBase::IsOriginAvailable(const std::wstring & origin_url)
|
||||
// default: empty
|
||||
std::vector<std::wstring> allowed_cors_origins;
|
||||
std::vector<std::wstring> allowed_origins;
|
||||
|
||||
// whether or not all origins are allowed if allowed_origins is empty
|
||||
// default: true
|
||||
// this is true by default because Origin header is sent not only in cors requests
|
||||
// (you can still allow it in your function/controller by overriding IsOriginAvailable(...) method)
|
||||
bool allow_all_origins;
|
||||
|
||||
// whether or not cors preflight requests are available
|
||||
// https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
|
||||
// default: false
|
||||
bool are_cors_preflight_requests_available;
|
||||
|
||||
// list of additional headers sent in Access-Control-Expose-Headers header
|
||||
// can be set per controller in a method: virtual void FunctionBase::AddAccessControlExposeHeadersHeader()
|
||||
|
|
|
@ -158,20 +158,23 @@ bool FunctionBase::IsCorsMethodAvailable(Request::Method method)
|
|||
}
|
||||
|
||||
|
||||
bool FunctionBase::IsCorsOriginAvailable(const std::wstring & origin_url)
|
||||
bool FunctionBase::IsOriginAvailable(const std::wstring & origin_url)
|
||||
{
|
||||
if( config )
|
||||
{
|
||||
if( config->allow_all_cors_origins )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if( !config->allowed_origins.empty() )
|
||||
{
|
||||
// origin_url can be a "null" string
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
|
||||
// but in such a case the "null" should be put to the config as well
|
||||
return is_in_list(origin_url, config->allowed_cors_origins);
|
||||
return is_in_list(origin_url, config->allowed_origins);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( config->allow_all_origins )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,15 +215,18 @@ void FunctionBase::AddAccessControlAllowOriginHeader(const std::wstring & origin
|
|||
{
|
||||
if( config )
|
||||
{
|
||||
if( config->allow_all_cors_origins )
|
||||
if( !config->allowed_origins.empty() )
|
||||
{
|
||||
cur->request->AddHeader(Header::access_control_allow_origin, L"*");
|
||||
// method IsOriginAvailable(..) was called beforehand so now we assume
|
||||
// that the origin_url is permitted (and is valid as a header)
|
||||
cur->request->AddHeader(Header::access_control_allow_origin, origin_url);
|
||||
}
|
||||
else
|
||||
{
|
||||
// method IsCorsOriginAvailable(..) was called beforehand so now we assume
|
||||
// that the origin_url is permitted
|
||||
cur->request->AddHeader(Header::access_control_allow_origin, origin_url);
|
||||
if( config->allow_all_origins )
|
||||
{
|
||||
cur->request->AddHeader(Header::access_control_allow_origin, L"*");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -307,12 +313,47 @@ void FunctionBase::AddCorsNormalRequestHeaders(const std::wstring & origin)
|
|||
}
|
||||
|
||||
|
||||
void FunctionBase::CheckCorsPreflightRequest(const std::wstring & origin, const std::wstring & method_string)
|
||||
{
|
||||
pt::Space * cors_headers = cur->request->headers_in.get_space_nc(L"Access_Control_Request_Headers");
|
||||
Request::Method method = Request::CheckRequestMethod(method_string.c_str());
|
||||
|
||||
if( IsCorsMethodAvailable(method) )
|
||||
{
|
||||
bool cors_headers_available = true;
|
||||
std::wstring * headers = nullptr;
|
||||
|
||||
if( cors_headers && cors_headers->is_wstr() )
|
||||
{
|
||||
headers = cors_headers->get_wstr();
|
||||
cors_headers_available = AreCorsHeadersAvailable(*headers);
|
||||
}
|
||||
|
||||
if( cors_headers_available )
|
||||
{
|
||||
AddCorsPreflightRequestHeaders(origin, method, headers);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( headers )
|
||||
{
|
||||
log << log2 << "FunctionBase: these cors headers: " << *headers << " are not permitted in cors requests" << logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "FunctionBase: this method: " << method_string << " is not permitted in cors requests" << logend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FunctionBase::AddResponseHeadersForOrigin(const std::wstring & origin)
|
||||
{
|
||||
if( cur->request->method == Request::Method::options )
|
||||
{
|
||||
pt::Space * cors_method = cur->request->headers_in.get_space_nc(L"Access_Control_Request_Method"); // FastCGI changes '-' to '_'
|
||||
pt::Space * cors_headers = cur->request->headers_in.get_space_nc(L"Access_Control_Request_Headers");
|
||||
cur->request->http_status = Header::status_204_no_content;
|
||||
|
||||
if( cors_method && cors_method->is_wstr() )
|
||||
{
|
||||
|
@ -321,35 +362,14 @@ void FunctionBase::AddResponseHeadersForOrigin(const std::wstring & origin)
|
|||
* https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
|
||||
* (we allow Access-Control-Request-Headers not to be present)
|
||||
*/
|
||||
Request::Method method = Request::CheckRequestMethod(cors_method->get_wstr()->c_str());
|
||||
cur->request->http_status = Header::status_204_no_content;
|
||||
|
||||
if( IsCorsMethodAvailable(method) )
|
||||
if( config->are_cors_preflight_requests_available )
|
||||
{
|
||||
bool cors_headers_available = true;
|
||||
std::wstring * headers = nullptr;
|
||||
|
||||
if( cors_headers && cors_headers->is_wstr() )
|
||||
{
|
||||
headers = cors_headers->get_wstr();
|
||||
cors_headers_available = AreCorsHeadersAvailable(*headers);
|
||||
}
|
||||
|
||||
if( cors_headers_available )
|
||||
{
|
||||
AddCorsPreflightRequestHeaders(origin, method, headers);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( headers )
|
||||
{
|
||||
log << log2 << "FunctionBase: these cors headers: " << *headers << " are not permitted in cors requests" << logend;
|
||||
}
|
||||
}
|
||||
CheckCorsPreflightRequest(origin, *cors_method->get_wstr());
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "FunctionBase: this method: " << *cors_method->get_wstr() << " is not permitted in cors requests" << logend;
|
||||
log << log2 << "FunctionBase: cors requests are disabled" << logend;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -374,7 +394,7 @@ void FunctionBase::CheckOriginHeader()
|
|||
|
||||
if( origin && origin->is_wstr() )
|
||||
{
|
||||
if( IsCorsOriginAvailable(*origin->get_wstr()) )
|
||||
if( IsOriginAvailable(*origin->get_wstr()) )
|
||||
{
|
||||
AddResponseHeadersForOrigin(*origin->get_wstr());
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
virtual void AddAllowMethodsHeader();
|
||||
|
||||
virtual bool IsCorsMethodAvailable(Request::Method method);
|
||||
virtual bool IsCorsOriginAvailable(const std::wstring & origin_url);
|
||||
virtual bool IsOriginAvailable(const std::wstring & origin_url);
|
||||
virtual bool AreCorsCredentialsAvailable();
|
||||
virtual bool AreCorsHeadersAvailable(const std::wstring & headers);
|
||||
|
||||
|
@ -126,6 +126,7 @@ public:
|
|||
virtual void AddAccessControlExposeHeadersHeader();
|
||||
virtual void AddCorsPreflightRequestHeaders(const std::wstring & origin, Request::Method method, const std::wstring * request_headers);
|
||||
virtual void AddCorsNormalRequestHeaders(const std::wstring & origin);
|
||||
virtual void CheckCorsPreflightRequest(const std::wstring & origin, const std::wstring & method_string);
|
||||
virtual void AddResponseHeadersForOrigin(const std::wstring & origin);
|
||||
virtual void CheckOriginHeader();
|
||||
|
||||
|
|
Loading…
Reference in New Issue