refactor the algorithm for testing the cors
while here: - send cors headers even if the status is 404 - add: access_control_expose_headers config option - list of additional headers sent in Access-Control-Expose-Headers - add: access_control_allow_credentials config option - if true return Access-Control-Allow-Credentials header equal "true"
This commit is contained in:
@@ -654,8 +654,6 @@ void App::MakeRenameMeToABetterName()
|
||||
|
||||
|
||||
////////////////////////
|
||||
|
||||
|
||||
cur.request->PrepareAnswerType();
|
||||
|
||||
if( cur.session->ip_ban && cur.session->ip_ban->IsIPBanned() )
|
||||
@@ -669,6 +667,11 @@ void App::MakeRenameMeToABetterName()
|
||||
cur.request->http_status = Header::status_403_forbidden;
|
||||
}
|
||||
|
||||
if( cur.request->function )
|
||||
{
|
||||
cur.request->function->CheckOriginHeader();
|
||||
}
|
||||
|
||||
// cur.request->status can be changed by function_parser
|
||||
if( cur.request->status == WINIX_ERR_OK && cur.request->http_status == Header::status_200_ok )
|
||||
plugin.Call(WINIX_PREPARE_REQUEST);
|
||||
@@ -687,7 +690,9 @@ void App::MakeRenameMeToABetterName()
|
||||
|
||||
AddDefaultModels();
|
||||
|
||||
if( cur.request->status == WINIX_ERR_OK && cur.request->http_status == Header::status_200_ok )
|
||||
// what about 204 No Content from preflight requests? should we make MakeOptions()?
|
||||
if( (cur.request->status == WINIX_ERR_OK && cur.request->http_status == Header::status_200_ok) ||
|
||||
(cur.request->method == Request::Method::options && cur.request->http_status == Header::status_204_no_content))
|
||||
functions.MakeFunction();
|
||||
|
||||
if( cur.request->run_state == Request::RunState::normal_run )
|
||||
|
||||
@@ -353,6 +353,8 @@ void Config::AssignValues()
|
||||
|
||||
allow_all_cors_origins = Bool(L"allow_all_cors_origins", false);
|
||||
ListText(L"allowed_cors_origins", allowed_cors_origins);
|
||||
ListText(L"access_control_expose_headers", access_control_expose_headers);
|
||||
access_control_allow_credentials = Bool(L"access_control_allow_credentials", false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -984,10 +984,23 @@ public:
|
||||
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
|
||||
// default: empty
|
||||
std::vector<std::wstring> allowed_cors_origins;
|
||||
|
||||
// list of additional headers sent in Access-Control-Expose-Headers header
|
||||
// can be set per controller in a method: virtual void FunctionBase::AddAccessControlExposeHeadersHeader()
|
||||
// default: empty
|
||||
std::vector<std::wstring> access_control_expose_headers;
|
||||
|
||||
// if true return Access-Control-Allow-Credentials header equal "true"
|
||||
// whethert credentials (e.g. cookies, authorization headers) are available in cors requests
|
||||
// can be set per controller in a method: virtual bool FunctionBase::AreCorsCredentialsAvailable()
|
||||
// default: false
|
||||
bool access_control_allow_credentials;
|
||||
|
||||
|
||||
|
||||
Config();
|
||||
bool ReadConfig(const std::wstring & config_file);
|
||||
|
||||
@@ -69,6 +69,47 @@ void Header::prepare_status_value(int http_status, pt::WTextStream & value, bool
|
||||
}
|
||||
|
||||
|
||||
bool Header::is_header_value_char_correct(wchar_t c)
|
||||
{
|
||||
/*
|
||||
* make sure to not allow at least \r or \r
|
||||
*/
|
||||
return c > 32 && c < 127;
|
||||
}
|
||||
|
||||
|
||||
bool Header::is_header_value_correct(const wchar_t * str)
|
||||
{
|
||||
for( ; *str ; ++str)
|
||||
{
|
||||
if( !is_header_value_char_correct(*str) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Header::is_header_value_correct(const std::wstring & str)
|
||||
{
|
||||
/*
|
||||
* dont use is_header_value_correct(str.c_str()) as there can be a null character (0) inside the string
|
||||
*/
|
||||
for(size_t i=0 ; i < str.size() ; ++i)
|
||||
{
|
||||
if( !is_header_value_char_correct(str[i]) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -54,10 +54,13 @@ public:
|
||||
static constexpr const wchar_t * accept_language = L"Accept-Language";
|
||||
static constexpr const wchar_t * authorization = L"Authorization";
|
||||
static constexpr const wchar_t * allow = L"Allow";
|
||||
static constexpr const wchar_t * very = L"Very";
|
||||
static constexpr const wchar_t * origin = L"Origin";
|
||||
static constexpr const wchar_t * access_control_allow_methods = L"Access-Control-Allow-Methods";
|
||||
static constexpr const wchar_t * access_control_allow_origin = L"Access-Control-Allow-Origin";
|
||||
static constexpr const wchar_t * access_control_allow_headers = L"Access-Control-Allow-Headers";
|
||||
static constexpr const wchar_t * access_control_allow_credentials = L"Access-Control-Allow-Credentials";
|
||||
static constexpr const wchar_t * access_control_expose_headers = L"Access-Control-Expose-Headers";
|
||||
static constexpr const wchar_t * access_control_max_age = L"Access-Control-Max-Age";
|
||||
|
||||
/*
|
||||
@@ -132,6 +135,9 @@ public:
|
||||
static const wchar_t * find_status_string_value(int http_status);
|
||||
static void prepare_status_value(int http_status, pt::WTextStream & value, bool clear_value = true);
|
||||
|
||||
static bool is_header_value_char_correct(wchar_t c);
|
||||
static bool is_header_value_correct(const wchar_t * str);
|
||||
static bool is_header_value_correct(const std::wstring & str);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -1531,37 +1531,10 @@ void Request::PrepareSessionCookie()
|
||||
}
|
||||
|
||||
|
||||
// preflight request are tested in function->MakeOption()
|
||||
void Request::CheckCorsHeaders()
|
||||
{
|
||||
pt::Space * origin = headers_in.get_space_nc(L"Origin");
|
||||
|
||||
if( origin && origin->is_wstr() && function )
|
||||
{
|
||||
if( !out_headers.has_key(Header::access_control_allow_origin) )
|
||||
{
|
||||
if( function->IsCorsOriginAvailable(*origin->get_wstr()) )
|
||||
{
|
||||
function->AddAccessControlAllowOriginHeader(*origin->get_wstr());
|
||||
}
|
||||
}
|
||||
|
||||
if( !out_headers.has_key(Header::access_control_allow_credentials) )
|
||||
{
|
||||
if( function->AreCorsCredentialsAvailable() )
|
||||
{
|
||||
function->AddAccessControlAllowCredentialsHeader();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Request::PrepareHeaders(bool compressing, int compress_encoding, size_t output_size)
|
||||
{
|
||||
PrepareSessionCookie();
|
||||
CheckCorsHeaders();
|
||||
|
||||
if( send_as_attachment )
|
||||
{
|
||||
|
||||
@@ -595,7 +595,6 @@ private:
|
||||
int SelectDeflateVersion();
|
||||
void SelectCompression(size_t source_len, bool & compression_allowed, int & compression_encoding);
|
||||
void PrepareSessionCookie();
|
||||
void CheckCorsHeaders();
|
||||
void PrepareHeaders(bool compressing, int compress_encoding, size_t output_size);
|
||||
void ModifyStatusForRedirect();
|
||||
void PrepareSendFileHeaderForStaticMountpoint();
|
||||
|
||||
Reference in New Issue
Block a user