// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ #define NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ #include #include #include #include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/time/time.h" #include "net/http/http_status_code.h" namespace net::test_server { class HttpResponse; // Delegate that actually sends the response bytes. Any response created should // be owned by the delegate that passed in via HttpResponse::SendResponse(). class HttpResponseDelegate { public: HttpResponseDelegate(); virtual ~HttpResponseDelegate(); HttpResponseDelegate(HttpResponseDelegate&) = delete; HttpResponseDelegate& operator=(const HttpResponseDelegate&) = delete; // The delegate needs to take ownership of the response to ensure the // response can stay alive until the delegate has finished sending it. virtual void AddResponse(std::unique_ptr response) = 0; // Builds and sends header block. Should only be called once. virtual void SendResponseHeaders(HttpStatusCode status, const std::string& status_reason, const base::StringPairs& headers) = 0; // Sends a raw header block, in the form of an HTTP1.1 response header block // (separated by "\r\n". Best effort will be maintained to preserve the raw // headers. virtual void SendRawResponseHeaders(const std::string& headers) = 0; // Sends a content block, then calls the closure. virtual void SendContents(const std::string& contents, base::OnceClosure callback = base::DoNothing()) = 0; // Called after the last content block or after the header block. The response // will hang until this is called. virtual void FinishResponse() = 0; // The following functions are essentially shorthand for common combinations // of function calls that may have a more efficient layout than just calling // one after the other. virtual void SendContentsAndFinish(const std::string& contents) = 0; virtual void SendHeadersContentAndFinish(HttpStatusCode status, const std::string& status_reason, const base::StringPairs& headers, const std::string& contents) = 0; }; // Interface for HTTP response implementations. The response should be owned by // the HttpResponseDelegate passed into SendResponse(), and should stay alive // until FinishResponse() is called on the delegate (or the owning delegate is // destroyed). class HttpResponse { public: virtual ~HttpResponse(); // Note that this is a WeakPtr. WeakPtrs can not be dereferenced or // invalidated outside of the thread that created them, so any use of the // delegate must either be from the same thread or posted to the original // task runner virtual void SendResponse(base::WeakPtr delegate) = 0; }; // This class is used to handle basic HTTP responses with commonly used // response headers such as "Content-Type". Sends the response immediately. class BasicHttpResponse : public HttpResponse { public: BasicHttpResponse(); BasicHttpResponse(const BasicHttpResponse&) = delete; BasicHttpResponse& operator=(const BasicHttpResponse&) = delete; ~BasicHttpResponse() override; // The response code. HttpStatusCode code() const { return code_; } void set_code(HttpStatusCode code) { code_ = code; } std::string reason() const { if (reason_) { return *reason_; } else { return GetHttpReasonPhrase(code_); } } void set_reason(std::optional reason) { reason_ = std::move(reason); } // The content of the response. const std::string& content() const { return content_; } void set_content(std::string_view content) { content_ = std::string{content}; } // The content type. const std::string& content_type() const { return content_type_; } void set_content_type(std::string_view content_type) { content_type_ = std::string{content_type}; } // Adds a custom header. void AddCustomHeader(std::string_view key, std::string_view value) { custom_headers_.emplace_back(key, value); } // Generates and returns a http response string. std::string ToResponseString() const; base::StringPairs BuildHeaders() const; void SendResponse(base::WeakPtr delegate) override; private: HttpStatusCode code_ = HTTP_OK; std::optional reason_; std::string content_; std::string content_type_; base::StringPairs custom_headers_; base::WeakPtrFactory weak_factory_{this}; }; class DelayedHttpResponse : public BasicHttpResponse { public: explicit DelayedHttpResponse(const base::TimeDelta delay); DelayedHttpResponse(const DelayedHttpResponse&) = delete; DelayedHttpResponse& operator=(const DelayedHttpResponse&) = delete; ~DelayedHttpResponse() override; // Issues a delayed send to the to the task runner. void SendResponse(base::WeakPtr delegate) override; private: // The delay time for the response. const base::TimeDelta delay_; }; class RawHttpResponse : public HttpResponse { public: RawHttpResponse(const std::string& headers, const std::string& contents); RawHttpResponse(const RawHttpResponse&) = delete; RawHttpResponse& operator=(const RawHttpResponse&) = delete; ~RawHttpResponse() override; void SendResponse(base::WeakPtr delegate) override; void AddHeader(const std::string& key_value_pair); private: std::string headers_; const std::string contents_; }; // "Response" where the server doesn't actually respond until the server is // destroyed. class HungResponse : public HttpResponse { public: HungResponse() = default; HungResponse(const HungResponse&) = delete; HungResponse& operator=(const HungResponse&) = delete; ~HungResponse() override = default; void SendResponse(base::WeakPtr delegate) override; }; // Return headers, then hangs. class HungAfterHeadersHttpResponse : public HttpResponse { public: explicit HungAfterHeadersHttpResponse(base::StringPairs headers = {}); ~HungAfterHeadersHttpResponse() override; void SendResponse(base::WeakPtr delegate) override; private: base::StringPairs headers_; }; } // namespace net::test_server #endif // NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_