xref: /aosp_15_r20/external/cronet/net/test/embedded_test_server/controllable_http_response.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 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 #include "net/test/embedded_test_server/controllable_http_response.h"
6 
7 #include "base/check_op.h"
8 #include "base/functional/bind.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/task/single_thread_task_runner.h"
11 #include "net/base/tracing.h"
12 #include "net/test/embedded_test_server/http_response.h"
13 
14 namespace net::test_server {
15 
16 class ControllableHttpResponse::Interceptor : public HttpResponse {
17  public:
Interceptor(base::WeakPtr<ControllableHttpResponse> controller,scoped_refptr<base::SingleThreadTaskRunner> controller_task_runner,const HttpRequest & http_request)18   explicit Interceptor(
19       base::WeakPtr<ControllableHttpResponse> controller,
20       scoped_refptr<base::SingleThreadTaskRunner> controller_task_runner,
21       const HttpRequest& http_request)
22       : controller_(controller),
23         controller_task_runner_(controller_task_runner),
24         http_request_(std::make_unique<HttpRequest>(http_request)) {}
25 
26   Interceptor(const Interceptor&) = delete;
27   Interceptor& operator=(const Interceptor&) = delete;
28 
29   ~Interceptor() override = default;
30 
31  private:
SendResponse(base::WeakPtr<HttpResponseDelegate> delegate)32   void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override {
33     scoped_refptr<base::SingleThreadTaskRunner> task_runner =
34         base::SingleThreadTaskRunner::GetCurrentDefault();
35     CHECK(task_runner);
36     controller_task_runner_->PostTask(
37         FROM_HERE, base::BindOnce(&ControllableHttpResponse::OnRequest,
38                                   controller_, std::move(task_runner), delegate,
39                                   std::move(http_request_)));
40   }
41 
42   base::WeakPtr<ControllableHttpResponse> controller_;
43   scoped_refptr<base::SingleThreadTaskRunner> controller_task_runner_;
44 
45   std::unique_ptr<HttpRequest> http_request_;
46 };
47 
ControllableHttpResponse(EmbeddedTestServer * embedded_test_server,const std::string & relative_url,bool relative_url_is_prefix)48 ControllableHttpResponse::ControllableHttpResponse(
49     EmbeddedTestServer* embedded_test_server,
50     const std::string& relative_url,
51     bool relative_url_is_prefix) {
52   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
53   embedded_test_server->RegisterRequestHandler(base::BindRepeating(
54       RequestHandler, weak_ptr_factory_.GetWeakPtr(),
55       base::SingleThreadTaskRunner::GetCurrentDefault(),
56       base::Owned(new bool(true)), relative_url, relative_url_is_prefix));
57 }
58 
59 ControllableHttpResponse::~ControllableHttpResponse() = default;
60 
WaitForRequest()61 void ControllableHttpResponse::WaitForRequest() {
62   TRACE_EVENT("test", "ControllableHttpResponse::WaitForRequest");
63   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
64   CHECK_EQ(State::WAITING_FOR_REQUEST, state_)
65       << "WaitForRequest() called twice.";
66   loop_.Run();
67   CHECK(embedded_test_server_task_runner_);
68   state_ = State::READY_TO_SEND_DATA;
69 }
70 
Send(net::HttpStatusCode http_status,const std::string & content_type,const std::string & content,const std::vector<std::string> & cookies,const std::vector<std::string> & extra_headers)71 void ControllableHttpResponse::Send(
72     net::HttpStatusCode http_status,
73     const std::string& content_type,
74     const std::string& content,
75     const std::vector<std::string>& cookies,
76     const std::vector<std::string>& extra_headers) {
77   TRACE_EVENT("test", "ControllableHttpResponse::Send", "http_status",
78               http_status, "content_type", content_type, "content", content,
79               "cookies", cookies);
80   std::string content_data(base::StringPrintf(
81       "HTTP/1.1 %d %s\nContent-type: %s\n", static_cast<int>(http_status),
82       net::GetHttpReasonPhrase(http_status), content_type.c_str()));
83   for (auto& cookie : cookies)
84     content_data += "Set-Cookie: " + cookie + "\n";
85   for (auto& header : extra_headers)
86     content_data += header + "\n";
87   content_data += "\n";
88   content_data += content;
89   Send(content_data);
90 }
91 
Send(const std::string & bytes)92 void ControllableHttpResponse::Send(const std::string& bytes) {
93   TRACE_EVENT("test", "ControllableHttpResponse::Send", "bytes", bytes);
94   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
95   CHECK_EQ(State::READY_TO_SEND_DATA, state_) << "Send() called without any "
96                                                  "opened connection. Did you "
97                                                  "call WaitForRequest()?";
98   base::RunLoop loop;
99   embedded_test_server_task_runner_->PostTask(
100       FROM_HERE, base::BindOnce(&HttpResponseDelegate::SendContents, delegate_,
101                                 bytes, loop.QuitClosure()));
102   loop.Run();
103 }
104 
Done()105 void ControllableHttpResponse::Done() {
106   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
107   CHECK_EQ(State::READY_TO_SEND_DATA, state_) << "Done() called without any "
108                                                  "opened connection. Did you "
109                                                  "call WaitForRequest()?";
110   embedded_test_server_task_runner_->PostTask(
111       FROM_HERE,
112       base::BindOnce(&HttpResponseDelegate::FinishResponse, delegate_));
113   state_ = State::DONE;
114 }
115 
has_received_request()116 bool ControllableHttpResponse::has_received_request() {
117   return loop_.AnyQuitCalled();
118 }
119 
OnRequest(scoped_refptr<base::SingleThreadTaskRunner> embedded_test_server_task_runner,base::WeakPtr<HttpResponseDelegate> delegate,std::unique_ptr<HttpRequest> http_request)120 void ControllableHttpResponse::OnRequest(
121     scoped_refptr<base::SingleThreadTaskRunner>
122         embedded_test_server_task_runner,
123     base::WeakPtr<HttpResponseDelegate> delegate,
124     std::unique_ptr<HttpRequest> http_request) {
125   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
126   CHECK(embedded_test_server_task_runner);
127   CHECK(!embedded_test_server_task_runner_)
128       << "A ControllableHttpResponse can only handle one request at a time";
129   embedded_test_server_task_runner_ = embedded_test_server_task_runner;
130   delegate_ = delegate;
131   http_request_ = std::move(http_request);
132   loop_.Quit();
133 }
134 
135 // Helper function used in the ControllableHttpResponse constructor.
136 // static
RequestHandler(base::WeakPtr<ControllableHttpResponse> controller,scoped_refptr<base::SingleThreadTaskRunner> controller_task_runner,bool * available,const std::string & relative_url,bool relative_url_is_prefix,const HttpRequest & request)137 std::unique_ptr<HttpResponse> ControllableHttpResponse::RequestHandler(
138     base::WeakPtr<ControllableHttpResponse> controller,
139     scoped_refptr<base::SingleThreadTaskRunner> controller_task_runner,
140     bool* available,
141     const std::string& relative_url,
142     bool relative_url_is_prefix,
143     const HttpRequest& request) {
144   if (!*available)
145     return nullptr;
146 
147   if (request.relative_url == relative_url ||
148       (relative_url_is_prefix &&
149        request.relative_url.starts_with(relative_url))) {
150     *available = false;
151     return std::make_unique<ControllableHttpResponse::Interceptor>(
152         controller, controller_task_runner, request);
153   }
154 
155   return nullptr;
156 }
157 
158 }  // namespace net::test_server
159