We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / tools / quic / test_tools / http_message.cc
blobcb322550a8816d986b0a01eb07e7f42a39ede59f
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.
5 #include "net/tools/quic/test_tools/http_message.h"
7 #include <vector>
9 #include "base/basictypes.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
13 using base::StringPiece;
14 using std::string;
15 using std::vector;
17 namespace net {
18 namespace tools {
19 namespace test {
21 namespace {
23 //const char kContentEncoding[] = "content-encoding";
24 const char kContentLength[] = "content-length";
25 const char kTransferCoding[] = "transfer-encoding";
27 // Both kHTTPVersionString and kMethodString arrays are constructed to match
28 // the enum values defined in Version and Method of HTTPMessage.
29 const char* const kHTTPVersionString[] = {
30 "",
31 "HTTP/0.9",
32 "HTTP/1.0",
33 "HTTP/1.1"
36 const char* const kMethodString[] = {
37 "",
38 "OPTIONS",
39 "GET",
40 "HEAD",
41 "POST",
42 "PUT",
43 "DELETE",
44 "TRACE",
45 "CONNECT",
46 "MKCOL",
47 "UNLOCK",
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;
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();
72 } // namespace
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);
81 return HttpConstants::UNKNOWN_METHOD;
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);
91 return HttpConstants::HTTP_UNKNOWN;
94 const char* HTTPMessage::MethodToString(Method method) {
95 CHECK_LT(static_cast<size_t>(method), arraysize(kMethodString));
96 return kMethodString[method];
99 const char* HTTPMessage::VersionToString(Version version) {
100 CHECK_LT(static_cast<size_t>(version), arraysize(kHTTPVersionString));
101 return kHTTPVersionString[version];
104 HTTPMessage::HTTPMessage()
105 : is_request_(true) {
106 InitializeFields();
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));
115 headers()->SetRequestMethod(MethodToString(request));
116 headers()->SetRequestUri(path);
119 HTTPMessage::~HTTPMessage() {
122 void HTTPMessage::InitializeFields() {
123 has_complete_message_ = true;
124 skip_message_validation_ = false;
127 void HTTPMessage::AddHeader(const string& header, const string& value) {
128 headers()->AppendHeader(header, value);
131 void HTTPMessage::RemoveHeader(const string& header) {
132 headers()->RemoveAllOfHeader(header);
135 void HTTPMessage::ReplaceHeader(const string& header, const string& value) {
136 headers()->ReplaceOrAppendHeader(header, value);
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);
150 void HTTPMessage::ValidateMessage() const {
151 if (skip_message_validation_) {
152 return;
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;
165 vector<StringPiece> content_lengths;
166 headers()->GetAllOfHeader(kContentLength, &content_lengths);
167 CHECK_GE(1ul, content_lengths.size());
169 CHECK_EQ(has_complete_message_, IsCompleteMessage(*this));
172 } // namespace test
173 } // namespace tools
174 } // namespace net