diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/http/http_util.cc | 48 | ||||
-rw-r--r-- | net/http/http_util.h | 22 | ||||
-rw-r--r-- | net/http/http_util_unittest.cc | 18 |
3 files changed, 85 insertions, 3 deletions
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index d69012c..95beb9c 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc @@ -57,7 +57,7 @@ std::string HttpUtil::PathForRequest(const GURL& url) { DCHECK(url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https"))); if (url.has_query()) return url.path() + "?" + url.query(); - return url.path(); + return url.path(); } // static @@ -430,7 +430,7 @@ std::string HttpUtil::AssembleRawHeaders(const char* input_begin, while (lines.GetNext()) { const char* line_begin = lines.token_begin(); const char* line_end = lines.token_end(); - + if (prev_line_continuable && IsLWS(*line_begin)) { // Join continuation; reduce the leading LWS to a single SP. raw_headers.push_back(' '); @@ -451,6 +451,50 @@ std::string HttpUtil::AssembleRawHeaders(const char* input_begin, return raw_headers; } +// TODO(jungshik): 1. If the list is 'fr-CA,fr-FR,en,de', we have to add +// 'fr' after 'fr-CA' with the same q-value as 'fr-CA' because +// web servers, in general, do not fall back to 'fr' and may end up picking +// 'en' which has a lower preference than 'fr-CA' and 'fr-FR'. +// 2. This function assumes that the input is a comma separated list +// without any whitespace. As long as it comes from the preference and +// a user does not manually edit the preference file, it's the case. Still, +// we may have to make it more robust. +std::string HttpUtil::GenerateAcceptLanguageHeader( + const std::string& raw_language_list) { + // We use integers for qvalue and qvalue decrement that are 10 times + // larger than actual values to avoid a problem with comparing + // two floating point numbers. + const unsigned int kQvalueDecrement10 = 2; + unsigned int qvalue10 = 10; + StringTokenizer t(raw_language_list, ","); + std::string lang_list_with_q; + while (t.GetNext()) { + std::string language = t.token(); + if (qvalue10 == 10) { + // q=1.0 is implicit. + lang_list_with_q = language; + } else { + DCHECK(qvalue10 >= 0 && qvalue10 < 10); + StringAppendF(&lang_list_with_q, ",%s;q=0.%d", language.c_str(), + qvalue10); + } + // It does not make sense to have 'q=0'. + if (qvalue10 > kQvalueDecrement10) + qvalue10 -= kQvalueDecrement10; + } + return lang_list_with_q; +} + +std::string HttpUtil::GenerateAcceptCharsetHeader(const std::string& charset) { + std::string charset_with_q = charset; + if (LowerCaseEqualsASCII(charset, "utf-8")) { + charset_with_q += ",*;q=0.5"; + } else { + charset_with_q += ",utf-8;q=0.7,*;q=0.3"; + } + return charset_with_q; +} + // BNF from section 4.2 of RFC 2616: // // message-header = field-name ":" [ field-value ] diff --git a/net/http/http_util.h b/net/http/http_util.h index d46ace4..9966c60 100644 --- a/net/http/http_util.h +++ b/net/http/http_util.h @@ -102,6 +102,28 @@ class HttpUtil { // the end-of-headers marker as defined by LocateEndOfHeaders. static std::string AssembleRawHeaders(const char* buf, int buf_len); + // Given a comma separated ordered list of language codes, return + // the list with a qvalue appended to each language. + // The way qvalues are assigned is rather simple. The qvalue + // starts with 1.0 and is decremented by 0.2 for each successive entry + // in the list until it reaches 0.2. All the entries after that are + // assigned the same qvalue of 0.2. Also, note that the 1st language + // will not have a qvalue added because the absence of a qvalue implicitly + // means q=1.0. + // + // When making a http request, this should be used to determine what + // to put in Accept-Language header. If a comma separated list of language + // codes *without* qvalue is sent, web servers regard all + // of them as having q=1.0 and pick one of them even though it may not + // be at the beginning of the list (see http://crbug.com/5899). + static std::string GenerateAcceptLanguageHeader( + const std::string& raw_language_list); + + // Given a charset, return the list with a qvalue. If charset is utf-8, + // it will return 'utf-8,*;q=0.5'. Otherwise (e.g. 'euc-jp'), it'll return + // 'euc-jp,utf-8;q=0.7,*;q=0.3'. + static std::string GenerateAcceptCharsetHeader(const std::string& charset); + // Used to iterate over the name/value pairs of HTTP headers. To iterate // over the values in a multi-value header, use ValuesIterator. // See AssembleRawHeaders for joining line continuations (this iterator diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index 4b27a0a..fab1953 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc @@ -326,7 +326,7 @@ TEST(HttpUtilTest, AssembleRawHeaders) { // Unterminated status line. { "HTTP/1.0 200 OK", - + "HTTP/1.0 200 OK||" }, @@ -475,3 +475,19 @@ TEST(HttpUtilTest, RequestUrlSanitize) { EXPECT_EQ(expected_path, HttpUtil::PathForRequest(url)); } } + +TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { + EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"), + HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de")); + EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2," + "ja;q=0.2"), + HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja")); +} + +TEST(HttpUtilTest, GenerateAcceptCharsetHeader) { + EXPECT_EQ(std::string("utf-8,*;q=0.5"), + HttpUtil::GenerateAcceptCharsetHeader("utf-8")); + EXPECT_EQ(std::string("EUC-JP,utf-8;q=0.7,*;q=0.3"), + HttpUtil::GenerateAcceptCharsetHeader("EUC-JP")); +} + |