User language control via userlang cookie

This commit is contained in:
Veloman Yunkan 2022-11-28 13:43:20 +04:00 committed by Matthieu Gautier
parent 600ff07986
commit 14f0f79061
3 changed files with 81 additions and 0 deletions

View File

@ -97,6 +97,7 @@ RequestContext::RequestContext(struct MHD_Connection* connection,
{ {
MHD_get_connection_values(connection, MHD_HEADER_KIND, &RequestContext::fill_header, this); MHD_get_connection_values(connection, MHD_HEADER_KIND, &RequestContext::fill_header, this);
MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &RequestContext::fill_argument, this); MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, &RequestContext::fill_argument, this);
MHD_get_connection_values(connection, MHD_COOKIE_KIND, &RequestContext::fill_cookie, this);
try { try {
acceptEncodingGzip = acceptEncodingGzip =
@ -106,6 +107,8 @@ RequestContext::RequestContext(struct MHD_Connection* connection,
try { try {
byteRange_ = ByteRange::parse(get_header(MHD_HTTP_HEADER_RANGE)); byteRange_ = ByteRange::parse(get_header(MHD_HTTP_HEADER_RANGE));
} catch (const std::out_of_range&) {} } catch (const std::out_of_range&) {}
userlang = determine_user_language();
} }
RequestContext::~RequestContext() RequestContext::~RequestContext()
@ -135,6 +138,14 @@ MHD_Result RequestContext::fill_argument(void *__this, enum MHD_ValueKind kind,
return MHD_YES; return MHD_YES;
} }
MHD_Result RequestContext::fill_cookie(void *__this, enum MHD_ValueKind kind,
const char *key, const char* value)
{
RequestContext *_this = static_cast<RequestContext*>(__this);
_this->cookies[key] = value == nullptr ? "" : value;
return MHD_YES;
}
void RequestContext::print_debug_info() const { void RequestContext::print_debug_info() const {
printf("method : %s (%d)\n", method==RequestMethod::GET ? "GET" : printf("method : %s (%d)\n", method==RequestMethod::GET ? "GET" :
method==RequestMethod::POST ? "POST" : method==RequestMethod::POST ? "POST" :
@ -215,11 +226,20 @@ std::string RequestContext::get_header(const std::string& name) const {
} }
std::string RequestContext::get_user_language() const std::string RequestContext::get_user_language() const
{
return userlang;
}
std::string RequestContext::determine_user_language() const
{ {
try { try {
return get_argument("userlang"); return get_argument("userlang");
} catch(const std::out_of_range&) {} } catch(const std::out_of_range&) {}
try {
return cookies.at("userlang");
} catch(const std::out_of_range&) {}
try { try {
return parseAcceptLanguageHeader(get_header("Accept-Language")); return parseAcceptLanguageHeader(get_header("Accept-Language"));
} catch(const std::out_of_range&) {} } catch(const std::out_of_range&) {}

View File

@ -130,10 +130,15 @@ class RequestContext {
ByteRange byteRange_; ByteRange byteRange_;
std::map<std::string, std::string> headers; std::map<std::string, std::string> headers;
std::map<std::string, std::vector<std::string>> arguments; std::map<std::string, std::vector<std::string>> arguments;
std::map<std::string, std::string> cookies;
std::string queryString; std::string queryString;
std::string userlang;
private: // functions private: // functions
std::string determine_user_language() const;
static MHD_Result fill_header(void *, enum MHD_ValueKind, const char*, const char*); static MHD_Result fill_header(void *, enum MHD_ValueKind, const char*, const char*);
static MHD_Result fill_cookie(void *, enum MHD_ValueKind, const char*, const char*);
static MHD_Result fill_argument(void *, enum MHD_ValueKind, const char*, const char*); static MHD_Result fill_argument(void *, enum MHD_ValueKind, const char*, const char*);
}; };

View File

@ -1042,6 +1042,46 @@ TEST_F(ServerTest, UserLanguageControl)
/*Response Set-Cookie:*/ "userlang=test", /*Response Set-Cookie:*/ "userlang=test",
/* expected <h1> */ "[I18N TESTING] Content not found, but at least the server is alive" /* expected <h1> */ "[I18N TESTING] Content not found, but at least the server is alive"
}, },
{
"userlang cookie is respected",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "",
/*Request Cookie:*/ "userlang=test",
/*Response Set-Cookie:*/ "userlang=test",
/* expected <h1> */ "[I18N TESTING] Content not found, but at least the server is alive"
},
{
"userlang cookie is correctly parsed",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "",
/*Request Cookie:*/ "anothercookie=123; userlang=test",
/*Response Set-Cookie:*/ "userlang=test",
/* expected <h1> */ "[I18N TESTING] Content not found, but at least the server is alive"
},
{
"userlang cookie is correctly parsed",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "",
/*Request Cookie:*/ "userlang=test; anothercookie=abc",
/*Response Set-Cookie:*/ "userlang=test",
/* expected <h1> */ "[I18N TESTING] Content not found, but at least the server is alive"
},
{
"userlang cookie is correctly parsed",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "",
/*Request Cookie:*/ "cookie1=abc; userlang=test; cookie2=xyz",
/*Response Set-Cookie:*/ "userlang=test",
/* expected <h1> */ "[I18N TESTING] Content not found, but at least the server is alive"
},
{
"Multiple userlang cookies are not a problem",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "",
/*Request Cookie:*/ "cookie1=abc; userlang=en; userlang=test; cookie2=xyz",
/*Response Set-Cookie:*/ "userlang=test",
/* expected <h1> */ "[I18N TESTING] Content not found, but at least the server is alive"
},
{ {
"userlang query parameter takes precedence over Accept-Language", "userlang query parameter takes precedence over Accept-Language",
/*url*/ "/ROOT/content/zimfile/invalid-article?userlang=en", /*url*/ "/ROOT/content/zimfile/invalid-article?userlang=en",
@ -1050,6 +1090,22 @@ TEST_F(ServerTest, UserLanguageControl)
/*Response Set-Cookie:*/ "userlang=en", /*Response Set-Cookie:*/ "userlang=en",
/* expected <h1> */ "Not Found" /* expected <h1> */ "Not Found"
}, },
{
"userlang query parameter takes precedence over its cookie counterpart",
/*url*/ "/ROOT/content/zimfile/invalid-article?userlang=en",
/*Accept-Language:*/ "",
/*Request Cookie:*/ "userlang=test",
/*Response Set-Cookie:*/ "userlang=en",
/* expected <h1> */ "Not Found"
},
{
"userlang in cookies takes precedence over Accept-Language",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "test",
/*Request Cookie:*/ "userlang=en",
/*Response Set-Cookie:*/ "userlang=en",
/* expected <h1> */ "Not Found"
},
{ {
"The value of the Accept-Language header is not currently parsed.", "The value of the Accept-Language header is not currently parsed.",
// In case of a comma separated list of languages (optionally weighted // In case of a comma separated list of languages (optionally weighted