| // 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 <string> |
| |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/callback_helpers.h" |
| #include "base/compiler_specific.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_piece.h" |
| #include "base/strings/string_split.h" |
| #include "base/time/time.h" |
| #include "net/http/http_status_code.h" |
| #include "third_party/abseil-cpp/absl/types/optional.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<HttpResponse> 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<HttpResponseDelegate> 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 { |
| return reason_.value_or(GetHttpReasonPhrase(code_)); |
| } |
| void set_reason(absl::optional<std::string> reason) { |
| reason_ = std::move(reason); |
| } |
| |
| // The content of the response. |
| const std::string& content() const { return content_; } |
| void set_content(base::StringPiece content) { |
| content_ = std::string{content}; |
| } |
| |
| // The content type. |
| const std::string& content_type() const { return content_type_; } |
| void set_content_type(base::StringPiece content_type) { |
| content_type_ = std::string{content_type}; |
| } |
| |
| // Adds a custom header. |
| void AddCustomHeader(base::StringPiece key, base::StringPiece 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<HttpResponseDelegate> delegate) override; |
| |
| private: |
| HttpStatusCode code_ = HTTP_OK; |
| absl::optional<std::string> reason_; |
| std::string content_; |
| std::string content_type_; |
| base::StringPairs custom_headers_; |
| base::WeakPtrFactory<BasicHttpResponse> 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<HttpResponseDelegate> 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<HttpResponseDelegate> 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<HttpResponseDelegate> delegate) override; |
| }; |
| |
| // Return headers, then hangs. |
| class HungAfterHeadersHttpResponse : public HttpResponse { |
| public: |
| explicit HungAfterHeadersHttpResponse(base::StringPairs headers = {}); |
| ~HungAfterHeadersHttpResponse() override; |
| |
| void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override; |
| |
| private: |
| base::StringPairs headers_; |
| }; |
| |
| } // namespace net::test_server |
| |
| #endif // NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ |