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) {