Fixed headers parsing in CurlHttpClient 1. substr(pos, pos_end) was used instead of substr(pos, pos_end - pos) 2. CURLOPT_HEADERFUNCTION is called for single header so no need to merge and split them later Change-Id: Iad852212258f870c2fe0683b0021ae99a020d12b Reviewed-on: https://weave-review.googlesource.com/1562 Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/examples/provider/curl_http_client.cc b/examples/provider/curl_http_client.cc index 32aa4af..774c07b 100644 --- a/examples/provider/curl_http_client.cc +++ b/examples/provider/curl_http_client.cc
@@ -34,6 +34,27 @@ return size * nmemb; } +size_t HeaderFunction(void* contents, size_t size, size_t nmemb, void* userp) { + std::string header(static_cast<const char*>(contents), size * nmemb); + auto pos = header.find(':'); + if (pos != std::string::npos) { + std::pair<std::string, std::string> header_pair; + + static const char kSpaces[] = " \t\r\n"; + header_pair.first = header.substr(0, pos); + pos = header.find_first_not_of(kSpaces, pos + 1); + if (pos != std::string::npos) { + auto last_non_space = header.find_last_not_of(kSpaces); + if (last_non_space >= pos) + header_pair.second = header.substr(pos, last_non_space - pos + 1); + } + + static_cast<provider::HttpClient::Headers*>(userp) + ->emplace_back(std::move(header_pair)); + } + return size * nmemb; +} + std::pair<std::unique_ptr<CurlHttpClient::Response>, ErrorPtr> SendRequestBlocking(CurlHttpClient::Method method, const std::string& url, @@ -76,9 +97,10 @@ CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response->data)); CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HEADERFUNCTION, - &WriteFunction)); - CHECK_EQ(CURLE_OK, curl_easy_setopt(curl.get(), CURLOPT_HEADERDATA, - &response->content_type)); + &HeaderFunction)); + provider::HttpClient::Headers response_headers; + CHECK_EQ(CURLE_OK, + curl_easy_setopt(curl.get(), CURLOPT_HEADERDATA, &response_headers)); CURLcode res = curl_easy_perform(curl.get()); if (chunk) @@ -91,20 +113,16 @@ return {nullptr, std::move(error)}; } - const std::string kContentType = "\r\nContent-Type:"; - auto pos = response->content_type.find(kContentType); - if (pos == std::string::npos) { + for (const auto& header : response_headers) { + if (header.first == "Content-Type") + response->content_type = header.second; + } + + if (response->content_type.empty()) { Error::AddTo(&error, FROM_HERE, "curl", "no_content_header", "Content-Type header is missing"); return {nullptr, std::move(error)}; } - pos += kContentType.size(); - auto pos_end = response->content_type.find("\r\n", pos); - if (pos_end == std::string::npos) { - pos_end = response->content_type.size(); - } - - response->content_type = response->content_type.substr(pos, pos_end); CHECK_EQ(CURLE_OK, curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &response->status));
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc index d2b10a9..8b8e752 100644 --- a/src/device_registration_info.cc +++ b/src/device_registration_info.cc
@@ -201,9 +201,9 @@ SplitAtFirst(response.GetContentType(), ";", true).first; if (content_type != http::kJson && content_type != http::kPlain) { - Error::AddTo(error, FROM_HERE, errors::json::kDomain, - "non_json_content_type", - "Unexpected response content type: " + content_type); + Error::AddTo( + error, FROM_HERE, errors::json::kDomain, "non_json_content_type", + "Unexpected content type: \'" + response.GetContentType() + "\'"); return std::unique_ptr<base::DictionaryValue>(); }
diff --git a/src/device_registration_info_unittest.cc b/src/device_registration_info_unittest.cc index 9edd396..8174b90 100644 --- a/src/device_registration_info_unittest.cc +++ b/src/device_registration_info_unittest.cc
@@ -222,10 +222,9 @@ url += "client_id="; url += test_data::kClientId; EXPECT_EQ(url, dev_reg_->GetOAuthURL( - "auth", - {{"redirect_uri", "urn:ietf:wg:oauth:2.0:oob"}, - {"response_type", "code"}, - {"client_id", test_data::kClientId}})); + "auth", {{"redirect_uri", "urn:ietf:wg:oauth:2.0:oob"}, + {"response_type", "code"}, + {"client_id", test_data::kClientId}})); } TEST_F(DeviceRegistrationInfoTest, HaveRegistrationCredentials) {