| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/tools/quic/test_tools/http_message_test_utils.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/basictypes.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/strings/string_number_conversions.h" | |
| 12 | |
| 13 using base::StringPiece; | |
| 14 using std::string; | |
| 15 using std::vector; | |
| 16 | |
| 17 namespace net { | |
| 18 namespace tools { | |
| 19 namespace test { | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 //const char* kContentEncoding = "content-encoding"; | |
| 24 const char* kContentLength = "content-length"; | |
| 25 const char* kTransferCoding = "transfer-encoding"; | |
| 26 | |
| 27 // Both kHTTPVersionString and kMethodString arrays are constructed to match | |
| 28 // the enum values defined in Version and Method of HTTPMessage. | |
| 29 const char* kHTTPVersionString[] = { | |
| 30 "", | |
| 31 "HTTP/0.9", | |
| 32 "HTTP/1.0", | |
| 33 "HTTP/1.1" | |
| 34 }; | |
| 35 | |
| 36 const char* kMethodString[] = { | |
| 37 "", | |
| 38 "OPTIONS", | |
| 39 "GET", | |
| 40 "HEAD", | |
| 41 "POST", | |
| 42 "PUT", | |
| 43 "DELETE", | |
| 44 "TRACE", | |
| 45 "CONNECT", | |
| 46 "MKCOL", | |
| 47 "UNLOCK", | |
| 48 }; | |
| 49 | |
| 50 // Returns true if the message represents a complete request or response. | |
| 51 // Messages are considered complete if: | |
| 52 // - Transfer-Encoding: chunked is present and message has a final chunk. | |
| 53 // - Content-Length header is present and matches the message body length. | |
| 54 // - Neither Transfer-Encoding nor Content-Length is present and message | |
| 55 // is tagged as complete. | |
| 56 bool IsCompleteMessage(const HTTPMessage& message) { | |
| 57 const BalsaHeaders* headers = message.headers(); | |
| 58 StringPiece content_length = headers->GetHeader(kContentLength); | |
| 59 if (!content_length.empty()) { | |
| 60 int parsed_content_length; | |
| 61 if (!base::StringToInt(content_length, &parsed_content_length)) { | |
| 62 return false; | |
| 63 } | |
| 64 return (message.body().size() == (uint)parsed_content_length); | |
| 65 } else { | |
| 66 // Assume messages without transfer coding or content-length are | |
| 67 // tagged correctly. | |
| 68 return message.has_complete_message(); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 } // namespace | |
| 73 | |
| 74 HTTPMessage::Method HTTPMessage::StringToMethod(StringPiece str) { | |
| 75 // Skip the first element of the array since it is empty string. | |
| 76 for (unsigned long i = 1; i < arraysize(kMethodString); ++i) { | |
| 77 if (strncmp(str.data(), kMethodString[i], str.length()) == 0) { | |
| 78 return static_cast<HTTPMessage::Method>(i); | |
| 79 } | |
| 80 } | |
| 81 return HttpConstants::UNKNOWN_METHOD; | |
| 82 } | |
| 83 | |
| 84 HTTPMessage::Version HTTPMessage::StringToVersion(StringPiece str) { | |
| 85 // Skip the first element of the array since it is empty string. | |
| 86 for (unsigned long i = 1; i < arraysize(kHTTPVersionString); ++i) { | |
| 87 if (strncmp(str.data(), kHTTPVersionString[i], str.length()) == 0) { | |
| 88 return static_cast<HTTPMessage::Version>(i); | |
| 89 } | |
| 90 } | |
| 91 return HttpConstants::HTTP_UNKNOWN; | |
| 92 } | |
| 93 | |
| 94 const char* HTTPMessage::MethodToString(Method method) { | |
| 95 CHECK_LT(static_cast<size_t>(method), arraysize(kMethodString)); | |
| 96 return kMethodString[method]; | |
| 97 } | |
| 98 | |
| 99 const char* HTTPMessage::VersionToString(Version version) { | |
| 100 CHECK_LT(static_cast<size_t>(version), arraysize(kHTTPVersionString)); | |
| 101 return kHTTPVersionString[version]; | |
| 102 } | |
| 103 | |
| 104 HTTPMessage::HTTPMessage() | |
| 105 : is_request_(true) { | |
| 106 InitializeFields(); | |
| 107 } | |
| 108 | |
| 109 HTTPMessage::HTTPMessage(Version ver, Method request, const string& path) | |
| 110 : is_request_(true) { | |
| 111 InitializeFields(); | |
| 112 if (ver != HttpConstants::HTTP_0_9) { | |
| 113 headers()->SetRequestVersion(VersionToString(ver)); | |
| 114 } | |
| 115 headers()->SetRequestMethod(MethodToString(request)); | |
| 116 headers()->SetRequestUri(path); | |
| 117 } | |
| 118 | |
| 119 HTTPMessage::~HTTPMessage() { | |
| 120 } | |
| 121 | |
| 122 void HTTPMessage::InitializeFields() { | |
| 123 has_complete_message_ = true; | |
| 124 skip_message_validation_ = false; | |
| 125 } | |
| 126 | |
| 127 void HTTPMessage::AddHeader(const string& header, const string& value) { | |
| 128 headers()->AppendHeader(header, value); | |
| 129 } | |
| 130 | |
| 131 void HTTPMessage::RemoveHeader(const string& header) { | |
| 132 headers()->RemoveAllOfHeader(header); | |
| 133 } | |
| 134 | |
| 135 void HTTPMessage::ReplaceHeader(const string& header, const string& value) { | |
| 136 headers()->ReplaceOrAppendHeader(header, value); | |
| 137 } | |
| 138 | |
| 139 void HTTPMessage::AddBody(const string& body, bool add_content_length) { | |
| 140 body_ = body; | |
| 141 // Remove any transfer-encoding that was left by a previous body. | |
| 142 RemoveHeader(kTransferCoding); | |
| 143 if (add_content_length) { | |
| 144 ReplaceHeader(kContentLength, base::IntToString(body.size())); | |
| 145 } else { | |
| 146 RemoveHeader(kContentLength); | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 void HTTPMessage::ValidateMessage() const { | |
| 151 if (skip_message_validation_) { | |
| 152 return; | |
| 153 } | |
| 154 | |
| 155 vector<StringPiece> transfer_encodings; | |
| 156 headers()->GetAllOfHeader(kTransferCoding, &transfer_encodings); | |
| 157 CHECK_GE(1ul, transfer_encodings.size()); | |
| 158 for (vector<StringPiece>::iterator it = transfer_encodings.begin(); | |
| 159 it != transfer_encodings.end(); | |
| 160 ++it) { | |
| 161 CHECK(StringPieceUtils::EqualIgnoreCase("identity", *it) || | |
| 162 StringPieceUtils::EqualIgnoreCase("chunked", *it)) << *it; | |
| 163 } | |
| 164 | |
| 165 vector<StringPiece> content_lengths; | |
| 166 headers()->GetAllOfHeader(kContentLength, &content_lengths); | |
| 167 CHECK_GE(1ul, content_lengths.size()); | |
| 168 | |
| 169 CHECK_EQ(has_complete_message_, IsCompleteMessage(*this)); | |
| 170 } | |
| 171 | |
| 172 } // namespace test | |
| 173 } // namespace tools | |
| 174 } // namespace net | |
| OLD | NEW |