Source release 16.4.0
This commit is contained in:
@@ -21,6 +21,10 @@ const int kConnectTimeoutMs = 15000;
|
||||
const int kWriteTimeoutMs = 12000;
|
||||
const int kReadTimeoutMs = 12000;
|
||||
|
||||
const std::string kGoogleHeaderUpper("X-Google");
|
||||
const std::string kGoogleHeaderLower("x-google");
|
||||
const std::string kCrLf("\r\n");
|
||||
|
||||
// Concatenate all chunks into one blob and returns the response with
|
||||
// header information.
|
||||
void ConcatenateChunkedResponse(const std::string http_response,
|
||||
@@ -37,7 +41,7 @@ void ConcatenateChunkedResponse(const std::string http_response,
|
||||
sscanf(&http_response[chunk_size_pos], "%zx", &chunk_size);
|
||||
if (chunk_size > http_response.size()) {
|
||||
// precaution, in case we misread chunk size
|
||||
LOGE("invalid chunk size %u", chunk_size);
|
||||
LOGE("Invalid chunk size %zu", chunk_size);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +52,6 @@ void ConcatenateChunkedResponse(const std::string http_response,
|
||||
// chunk size\r\n
|
||||
// chunk data\r\n
|
||||
// 0\r\n
|
||||
const std::string kCrLf = "\r\n";
|
||||
size_t chunk_pos = http_response.find(kCrLf, chunk_size_pos);
|
||||
modified_response->assign(http_response, 0, chunk_size_pos);
|
||||
|
||||
@@ -61,7 +64,7 @@ void ConcatenateChunkedResponse(const std::string http_response,
|
||||
sscanf(&http_response[chunk_size_pos], "%zx", &chunk_size);
|
||||
if (chunk_size > http_response.size()) {
|
||||
// precaution, in case we misread chunk size
|
||||
LOGE("invalid chunk size %u", chunk_size);
|
||||
LOGE("Invalid chunk size %zu", chunk_size);
|
||||
break;
|
||||
}
|
||||
chunk_pos = http_response.find(kCrLf, chunk_size_pos);
|
||||
@@ -101,11 +104,12 @@ bool UrlRequest::GetResponse(std::string* message) {
|
||||
// non-blocking mode.
|
||||
while (true) {
|
||||
char read_buffer[kReadBufferSize];
|
||||
int bytes = socket_.Read(read_buffer, sizeof(read_buffer), kReadTimeoutMs);
|
||||
const int bytes =
|
||||
socket_.Read(read_buffer, sizeof(read_buffer), kReadTimeoutMs);
|
||||
if (bytes > 0) {
|
||||
response.append(read_buffer, bytes);
|
||||
} else if (bytes < 0) {
|
||||
LOGE("read error, errno = %d", errno);
|
||||
LOGE("Read error, errno = %d", errno);
|
||||
return false;
|
||||
} else {
|
||||
// end of stream.
|
||||
@@ -114,7 +118,9 @@ bool UrlRequest::GetResponse(std::string* message) {
|
||||
}
|
||||
|
||||
ConcatenateChunkedResponse(response, message);
|
||||
LOGV("HTTP response: (%d): %s", message->size(), message->c_str());
|
||||
LOGV("HTTP response from %s://%s:%d%s: (%zu): %s", socket_.scheme().c_str(),
|
||||
socket_.domain_name().c_str(), socket_.port(),
|
||||
socket_.resource_path().c_str(), message->size(), message->c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -131,6 +137,45 @@ int UrlRequest::GetStatusCode(const std::string& response) {
|
||||
return status_code;
|
||||
}
|
||||
|
||||
// static
|
||||
bool UrlRequest::GetDebugHeaderFields(
|
||||
const std::string& response, std::map<std::string, std::string>* fields) {
|
||||
if (fields == nullptr) return false;
|
||||
fields->clear();
|
||||
|
||||
const auto find_next = [&](size_t pos) -> size_t {
|
||||
// Some of Google's HTTPS return header fields in lower case,
|
||||
// this lambda will check for both and return the position that
|
||||
// that is next or npos if none are found.
|
||||
const size_t lower_pos = response.find(kGoogleHeaderLower, pos + 1);
|
||||
const size_t upper_pos = response.find(kGoogleHeaderUpper, pos + 1);
|
||||
if (lower_pos == std::string::npos) return upper_pos;
|
||||
if (upper_pos == std::string::npos || lower_pos < upper_pos)
|
||||
return lower_pos;
|
||||
return upper_pos;
|
||||
};
|
||||
|
||||
// Search is relatively simple, and may pick up additional matches within
|
||||
// the body of the request. This is not anticiapted for the limited use
|
||||
// cases of parsing provisioning/license/renewal responses.
|
||||
for (size_t key_pos = find_next(0); key_pos != std::string::npos;
|
||||
key_pos = find_next(key_pos)) {
|
||||
const size_t end_key_pos = response.find(":", key_pos);
|
||||
const size_t end_value_pos = response.find(kCrLf, key_pos);
|
||||
// Skip if the colon cannot be found. Technically possible to find
|
||||
// "X-Google" inside the value of a nother header field.
|
||||
if (end_key_pos == std::string::npos || end_value_pos == std::string::npos)
|
||||
continue;
|
||||
const size_t value_pos = end_key_pos + 2;
|
||||
if (end_value_pos < value_pos) continue;
|
||||
const std::string key = response.substr(key_pos, end_key_pos - key_pos);
|
||||
const std::string value =
|
||||
response.substr(value_pos, end_value_pos - value_pos);
|
||||
fields->insert({key, value});
|
||||
}
|
||||
return !fields->empty();
|
||||
}
|
||||
|
||||
bool UrlRequest::PostRequestWithPath(const std::string& path,
|
||||
const std::string& data) {
|
||||
std::string request;
|
||||
@@ -160,7 +205,7 @@ bool UrlRequest::PostRequestWithPath(const std::string& path,
|
||||
|
||||
const int ret =
|
||||
socket_.Write(request.c_str(), request.size(), kWriteTimeoutMs);
|
||||
LOGV("HTTP request: (%d): %s", request.size(), b2a_hex(request).c_str());
|
||||
LOGV("HTTP request: (%zu): %s", request.size(), b2a_hex(request).c_str());
|
||||
return ret != -1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user