Log X-Google fields on failed HTTP requests.
[ Merge of http://go/wvgerrit/103395 ] To help with debugging failures in HTTP requests during unit tests, this CL adds logging for Google's debugging response header fields. These fields are of the type "X-Google-*" or "x-google-*" and provide information such as the service name, server cell, error details, and other details that can help isolate the cause of failure on the server's end. An additional unittest has been created to test the parser for the header fields. Tests that are known to exprience HTTP failures have been extended to include logs for these fields should they be present. Bug: 137619348 Test: Linux unit tests and Jenkins test Change-Id: I69959af2ba91510f345bbb02cf7ca35c3f1119da
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,
|
||||
@@ -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);
|
||||
|
||||
@@ -131,6 +134,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;
|
||||
|
||||
Reference in New Issue
Block a user