1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ 6 #define NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ 7 8 #include <optional> 9 #include <string> 10 #include <string_view> 11 12 #include "base/compiler_specific.h" 13 #include "base/functional/bind.h" 14 #include "base/functional/callback.h" 15 #include "base/functional/callback_helpers.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_split.h" 19 #include "base/time/time.h" 20 #include "net/http/http_status_code.h" 21 22 namespace net::test_server { 23 24 class HttpResponse; 25 26 // Delegate that actually sends the response bytes. Any response created should 27 // be owned by the delegate that passed in via HttpResponse::SendResponse(). 28 class HttpResponseDelegate { 29 public: 30 HttpResponseDelegate(); 31 virtual ~HttpResponseDelegate(); 32 HttpResponseDelegate(HttpResponseDelegate&) = delete; 33 HttpResponseDelegate& operator=(const HttpResponseDelegate&) = delete; 34 35 // The delegate needs to take ownership of the response to ensure the 36 // response can stay alive until the delegate has finished sending it. 37 virtual void AddResponse(std::unique_ptr<HttpResponse> response) = 0; 38 39 // Builds and sends header block. Should only be called once. 40 virtual void SendResponseHeaders(HttpStatusCode status, 41 const std::string& status_reason, 42 const base::StringPairs& headers) = 0; 43 // Sends a raw header block, in the form of an HTTP1.1 response header block 44 // (separated by "\r\n". Best effort will be maintained to preserve the raw 45 // headers. 46 virtual void SendRawResponseHeaders(const std::string& headers) = 0; 47 48 // Sends a content block, then calls the closure. 49 virtual void SendContents(const std::string& contents, 50 base::OnceClosure callback = base::DoNothing()) = 0; 51 52 // Called after the last content block or after the header block. The response 53 // will hang until this is called. 54 virtual void FinishResponse() = 0; 55 56 // The following functions are essentially shorthand for common combinations 57 // of function calls that may have a more efficient layout than just calling 58 // one after the other. 59 virtual void SendContentsAndFinish(const std::string& contents) = 0; 60 virtual void SendHeadersContentAndFinish(HttpStatusCode status, 61 const std::string& status_reason, 62 const base::StringPairs& headers, 63 const std::string& contents) = 0; 64 }; 65 66 // Interface for HTTP response implementations. The response should be owned by 67 // the HttpResponseDelegate passed into SendResponse(), and should stay alive 68 // until FinishResponse() is called on the delegate (or the owning delegate is 69 // destroyed). 70 class HttpResponse { 71 public: 72 virtual ~HttpResponse(); 73 74 // Note that this is a WeakPtr. WeakPtrs can not be dereferenced or 75 // invalidated outside of the thread that created them, so any use of the 76 // delegate must either be from the same thread or posted to the original 77 // task runner 78 virtual void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) = 0; 79 }; 80 81 // This class is used to handle basic HTTP responses with commonly used 82 // response headers such as "Content-Type". Sends the response immediately. 83 class BasicHttpResponse : public HttpResponse { 84 public: 85 BasicHttpResponse(); 86 87 BasicHttpResponse(const BasicHttpResponse&) = delete; 88 BasicHttpResponse& operator=(const BasicHttpResponse&) = delete; 89 90 ~BasicHttpResponse() override; 91 92 // The response code. code()93 HttpStatusCode code() const { return code_; } set_code(HttpStatusCode code)94 void set_code(HttpStatusCode code) { code_ = code; } 95 reason()96 std::string reason() const { 97 if (reason_) { 98 return *reason_; 99 } else { 100 return GetHttpReasonPhrase(code_); 101 } 102 } set_reason(std::optional<std::string> reason)103 void set_reason(std::optional<std::string> reason) { 104 reason_ = std::move(reason); 105 } 106 107 // The content of the response. content()108 const std::string& content() const { return content_; } set_content(std::string_view content)109 void set_content(std::string_view content) { 110 content_ = std::string{content}; 111 } 112 113 // The content type. content_type()114 const std::string& content_type() const { return content_type_; } set_content_type(std::string_view content_type)115 void set_content_type(std::string_view content_type) { 116 content_type_ = std::string{content_type}; 117 } 118 119 // Adds a custom header. AddCustomHeader(std::string_view key,std::string_view value)120 void AddCustomHeader(std::string_view key, std::string_view value) { 121 custom_headers_.emplace_back(key, value); 122 } 123 124 // Generates and returns a http response string. 125 std::string ToResponseString() const; 126 127 base::StringPairs BuildHeaders() const; 128 129 void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override; 130 131 private: 132 HttpStatusCode code_ = HTTP_OK; 133 std::optional<std::string> reason_; 134 std::string content_; 135 std::string content_type_; 136 base::StringPairs custom_headers_; 137 base::WeakPtrFactory<BasicHttpResponse> weak_factory_{this}; 138 }; 139 140 class DelayedHttpResponse : public BasicHttpResponse { 141 public: 142 explicit DelayedHttpResponse(const base::TimeDelta delay); 143 144 DelayedHttpResponse(const DelayedHttpResponse&) = delete; 145 DelayedHttpResponse& operator=(const DelayedHttpResponse&) = delete; 146 147 ~DelayedHttpResponse() override; 148 149 // Issues a delayed send to the to the task runner. 150 void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override; 151 152 private: 153 // The delay time for the response. 154 const base::TimeDelta delay_; 155 }; 156 157 class RawHttpResponse : public HttpResponse { 158 public: 159 RawHttpResponse(const std::string& headers, const std::string& contents); 160 161 RawHttpResponse(const RawHttpResponse&) = delete; 162 RawHttpResponse& operator=(const RawHttpResponse&) = delete; 163 164 ~RawHttpResponse() override; 165 166 void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override; 167 168 void AddHeader(const std::string& key_value_pair); 169 170 private: 171 std::string headers_; 172 const std::string contents_; 173 }; 174 175 // "Response" where the server doesn't actually respond until the server is 176 // destroyed. 177 class HungResponse : public HttpResponse { 178 public: 179 HungResponse() = default; 180 181 HungResponse(const HungResponse&) = delete; 182 HungResponse& operator=(const HungResponse&) = delete; 183 184 ~HungResponse() override = default; 185 186 void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override; 187 }; 188 189 // Return headers, then hangs. 190 class HungAfterHeadersHttpResponse : public HttpResponse { 191 public: 192 explicit HungAfterHeadersHttpResponse(base::StringPairs headers = {}); 193 ~HungAfterHeadersHttpResponse() override; 194 195 void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override; 196 197 private: 198 base::StringPairs headers_; 199 }; 200 201 } // namespace net::test_server 202 203 #endif // NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ 204