diff --git a/src/server/request_context.cpp b/src/server/request_context.cpp index 4eac4ad33..e7cfd1b4a 100644 --- a/src/server/request_context.cpp +++ b/src/server/request_context.cpp @@ -212,26 +212,32 @@ std::string RequestContext::get_header(const std::string& name) const { std::string RequestContext::get_user_language() const { - return userlang; + return userlang.lang; } -std::string RequestContext::determine_user_language() const +bool RequestContext::user_language_comes_from_cookie() const +{ + return userlang.selectedBy == UserLanguage::SelectorKind::COOKIE; +} + +RequestContext::UserLanguage RequestContext::determine_user_language() const { try { - return get_argument("userlang"); + return {UserLanguage::SelectorKind::QUERY_PARAM, get_argument("userlang")}; } catch(const std::out_of_range&) {} try { - return cookies.at("userlang"); + return {UserLanguage::SelectorKind::COOKIE, cookies.at("userlang")}; } catch(const std::out_of_range&) {} try { const std::string acceptLanguage = get_header("Accept-Language"); const auto userLangPrefs = parseUserLanguagePreferences(acceptLanguage); - return selectMostSuitableLanguage(userLangPrefs); + const auto lang = selectMostSuitableLanguage(userLangPrefs); + return {UserLanguage::SelectorKind::ACCEPT_LANGUAGE_HEADER, lang}; } catch(const std::out_of_range&) {} - return "en"; + return {UserLanguage::SelectorKind::DEFAULT, "en"}; } std::string RequestContext::get_requested_format() const diff --git a/src/server/request_context.h b/src/server/request_context.h index 07339324b..46bc81464 100644 --- a/src/server/request_context.h +++ b/src/server/request_context.h @@ -118,6 +118,23 @@ class RequestContext { std::string get_user_language() const; std::string get_requested_format() const; + bool user_language_comes_from_cookie() const; + + private: // types + struct UserLanguage + { + enum SelectorKind + { + QUERY_PARAM, + COOKIE, + ACCEPT_LANGUAGE_HEADER, + DEFAULT + }; + + SelectorKind selectedBy; + std::string lang; + }; + private: // data std::string full_url; std::string url; @@ -132,10 +149,10 @@ class RequestContext { std::map> arguments; std::map cookies; std::string queryString; - std::string userlang; + UserLanguage userlang; private: // functions - std::string determine_user_language() const; + UserLanguage determine_user_language() const; 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*); diff --git a/src/server/response.cpp b/src/server/response.cpp index c0cd8bd5d..d8127f3c4 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -387,8 +387,10 @@ MHD_Result Response::send(const RequestContext& request, MHD_Connection* connect MHD_add_response_header(response, p.first.c_str(), p.second.c_str()); } - const std::string cookie = "userlang=" + request.get_user_language(); - MHD_add_response_header(response, MHD_HTTP_HEADER_SET_COOKIE, cookie.c_str()); + if ( ! request.user_language_comes_from_cookie() ) { + const std::string cookie = "userlang=" + request.get_user_language(); + MHD_add_response_header(response, MHD_HTTP_HEADER_SET_COOKIE, cookie.c_str()); + } if (m_returnCode == MHD_HTTP_OK && m_byteRange.kind() == ByteRange::RESOLVED_PARTIAL_CONTENT) m_returnCode = MHD_HTTP_PARTIAL_CONTENT; diff --git a/test/server.cpp b/test/server.cpp index fd29ee685..0a1027eac 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -1047,7 +1047,7 @@ TEST_F(ServerTest, UserLanguageControl) /*url*/ "/ROOT/content/zimfile/invalid-article", /*Accept-Language:*/ "", /*Request Cookie:*/ "userlang=test", - /*Response Set-Cookie:*/ "userlang=test", + /*Response Set-Cookie:*/ NO_COOKIE, /* expected

*/ "[I18N TESTING] Content not found, but at least the server is alive" }, { @@ -1055,7 +1055,7 @@ TEST_F(ServerTest, UserLanguageControl) /*url*/ "/ROOT/content/zimfile/invalid-article", /*Accept-Language:*/ "", /*Request Cookie:*/ "anothercookie=123; userlang=test", - /*Response Set-Cookie:*/ "userlang=test", + /*Response Set-Cookie:*/ NO_COOKIE, /* expected

*/ "[I18N TESTING] Content not found, but at least the server is alive" }, { @@ -1063,7 +1063,7 @@ TEST_F(ServerTest, UserLanguageControl) /*url*/ "/ROOT/content/zimfile/invalid-article", /*Accept-Language:*/ "", /*Request Cookie:*/ "userlang=test; anothercookie=abc", - /*Response Set-Cookie:*/ "userlang=test", + /*Response Set-Cookie:*/ NO_COOKIE, /* expected

*/ "[I18N TESTING] Content not found, but at least the server is alive" }, { @@ -1071,7 +1071,7 @@ TEST_F(ServerTest, UserLanguageControl) /*url*/ "/ROOT/content/zimfile/invalid-article", /*Accept-Language:*/ "", /*Request Cookie:*/ "cookie1=abc; userlang=test; cookie2=xyz", - /*Response Set-Cookie:*/ "userlang=test", + /*Response Set-Cookie:*/ NO_COOKIE, /* expected

*/ "[I18N TESTING] Content not found, but at least the server is alive" }, { @@ -1079,7 +1079,7 @@ TEST_F(ServerTest, UserLanguageControl) /*url*/ "/ROOT/content/zimfile/invalid-article", /*Accept-Language:*/ "", /*Request Cookie:*/ "cookie1=abc; userlang=en; userlang=test; cookie2=xyz", - /*Response Set-Cookie:*/ "userlang=test", + /*Response Set-Cookie:*/ NO_COOKIE, /* expected

*/ "[I18N TESTING] Content not found, but at least the server is alive" }, { @@ -1103,7 +1103,7 @@ TEST_F(ServerTest, UserLanguageControl) /*url*/ "/ROOT/content/zimfile/invalid-article", /*Accept-Language:*/ "test", /*Request Cookie:*/ "userlang=en", - /*Response Set-Cookie:*/ "userlang=en", + /*Response Set-Cookie:*/ NO_COOKIE, /* expected

*/ "Not Found" }, {