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