diff options
Diffstat (limited to 'chromium/net/tools/quic/test_tools/http_message_test_utils.cc')
-rw-r--r-- | chromium/net/tools/quic/test_tools/http_message_test_utils.cc | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/chromium/net/tools/quic/test_tools/http_message_test_utils.cc b/chromium/net/tools/quic/test_tools/http_message_test_utils.cc new file mode 100644 index 00000000000..7d6df7a7649 --- /dev/null +++ b/chromium/net/tools/quic/test_tools/http_message_test_utils.cc @@ -0,0 +1,175 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/tools/quic/test_tools/http_message_test_utils.h" + +#include <vector> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" + +using base::StringPiece; +using std::string; +using std::vector; + +namespace net { +namespace tools { +namespace test { + +namespace { + +//const char* kContentEncoding = "content-encoding"; +const char* kContentLength = "content-length"; +const char* kTransferCoding = "transfer-encoding"; + +// Both kHTTPVersionString and kMethodString arrays are constructed to match +// the enum values defined in Version and Method of HTTPMessage. +const char* kHTTPVersionString[] = { + "", + "HTTP/0.9", + "HTTP/1.0", + "HTTP/1.1" +}; + +const char* kMethodString[] = { + "", + "OPTIONS", + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "TRACE", + "CONNECT", + "MKCOL", + "UNLOCK", +}; + +// Returns true if the message represents a complete request or response. +// Messages are considered complete if: +// - Transfer-Encoding: chunked is present and message has a final chunk. +// - Content-Length header is present and matches the message body length. +// - Neither Transfer-Encoding nor Content-Length is present and message +// is tagged as complete. +bool IsCompleteMessage(const HTTPMessage& message) { + return true; + const BalsaHeaders* headers = message.headers(); + StringPiece content_length = headers->GetHeader(kContentLength); + if (!content_length.empty()) { + int parsed_content_length; + if (!base::StringToInt(content_length, &parsed_content_length)) { + return false; + } + return (message.body().size() == (uint)parsed_content_length); + } else { + // Assume messages without transfer coding or content-length are + // tagged correctly. + return message.has_complete_message(); + } +} + +} // namespace + +HTTPMessage::Method HTTPMessage::StringToMethod(StringPiece str) { + // Skip the first element of the array since it is empty string. + for (unsigned long i = 1; i < arraysize(kMethodString); ++i) { + if (strncmp(str.data(), kMethodString[i], str.length()) == 0) { + return static_cast<HTTPMessage::Method>(i); + } + } + return HttpConstants::UNKNOWN_METHOD; +} + +HTTPMessage::Version HTTPMessage::StringToVersion(StringPiece str) { + // Skip the first element of the array since it is empty string. + for (unsigned long i = 1; i < arraysize(kHTTPVersionString); ++i) { + if (strncmp(str.data(), kHTTPVersionString[i], str.length()) == 0) { + return static_cast<HTTPMessage::Version>(i); + } + } + return HttpConstants::HTTP_UNKNOWN; +} + +const char* HTTPMessage::MethodToString(Method method) { + CHECK_LT(static_cast<size_t>(method), arraysize(kMethodString)); + return kMethodString[method]; +} + +const char* HTTPMessage::VersionToString(Version version) { + CHECK_LT(static_cast<size_t>(version), arraysize(kHTTPVersionString)); + return kHTTPVersionString[version]; +} + +HTTPMessage::HTTPMessage() + : is_request_(true) { + InitializeFields(); +} + +HTTPMessage::HTTPMessage(Version ver, Method request, const string& path) + : is_request_(true) { + InitializeFields(); + if (ver != HttpConstants::HTTP_0_9) { + headers()->SetRequestVersion(VersionToString(ver)); + } + headers()->SetRequestMethod(MethodToString(request)); + headers()->SetRequestUri(path); +} + +HTTPMessage::~HTTPMessage() { +} + +void HTTPMessage::InitializeFields() { + has_complete_message_ = true; + skip_message_validation_ = false; +} + +void HTTPMessage::AddHeader(const string& header, const string& value) { + headers()->AppendHeader(header, value); +} + +void HTTPMessage::RemoveHeader(const string& header) { + headers()->RemoveAllOfHeader(header); +} + +void HTTPMessage::ReplaceHeader(const string& header, const string& value) { + headers()->ReplaceOrAppendHeader(header, value); +} + +void HTTPMessage::AddBody(const string& body, bool add_content_length) { + body_ = body; + // Remove any transfer-encoding that was left by a previous body. + RemoveHeader(kTransferCoding); + if (add_content_length) { + ReplaceHeader(kContentLength, base::IntToString(body.size())); + } else { + RemoveHeader(kContentLength); + } +} + +void HTTPMessage::ValidateMessage() const { + if (skip_message_validation_) { + return; + } + + vector<StringPiece> transfer_encodings; + headers()->GetAllOfHeader(kTransferCoding, &transfer_encodings); + CHECK_GE(1ul, transfer_encodings.size()); + for (vector<StringPiece>::iterator it = transfer_encodings.begin(); + it != transfer_encodings.end(); + ++it) { + CHECK(StringPieceUtils::EqualIgnoreCase("identity", *it) || + StringPieceUtils::EqualIgnoreCase("chunked", *it)) << *it; + } + + vector<StringPiece> content_lengths; + headers()->GetAllOfHeader(kContentLength, &content_lengths); + CHECK_GE(1ul, content_lengths.size()); + + CHECK_EQ(has_complete_message_, IsCompleteMessage(*this)); +} + +} // namespace test +} // namespace tools +} // namespace net |