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