1 // Copyright 2021 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/http1_connection.h"
6
7 #include <string_view>
8 #include <utility>
9
10 #include "base/functional/bind.h"
11 #include "base/functional/callback_forward.h"
12 #include "base/functional/callback_helpers.h"
13 #include "base/strings/stringprintf.h"
14 #include "net/base/completion_once_callback.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/test_completion_callback.h"
17 #include "net/socket/stream_socket.h"
18 #include "net/test/embedded_test_server/embedded_test_server.h"
19 #include "net/test/embedded_test_server/http_response.h"
20 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
21
22 namespace net::test_server {
23
Http1Connection(std::unique_ptr<StreamSocket> socket,EmbeddedTestServerConnectionListener * connection_listener,EmbeddedTestServer * server_delegate)24 Http1Connection::Http1Connection(
25 std::unique_ptr<StreamSocket> socket,
26 EmbeddedTestServerConnectionListener* connection_listener,
27 EmbeddedTestServer* server_delegate)
28 : socket_(std::move(socket)),
29 connection_listener_(connection_listener),
30 server_delegate_(server_delegate),
31 read_buf_(base::MakeRefCounted<IOBufferWithSize>(4096)) {}
32
~Http1Connection()33 Http1Connection::~Http1Connection() {
34 weak_factory_.InvalidateWeakPtrs();
35 }
36
OnSocketReady()37 void Http1Connection::OnSocketReady() {
38 ReadData();
39 }
40
TakeSocket()41 std::unique_ptr<StreamSocket> Http1Connection::TakeSocket() {
42 return std::move(socket_);
43 }
44
Socket()45 StreamSocket* Http1Connection::Socket() {
46 return socket_.get();
47 }
48
GetWeakPtr()49 base::WeakPtr<HttpConnection> Http1Connection::GetWeakPtr() {
50 return weak_factory_.GetWeakPtr();
51 }
52
ReadData()53 void Http1Connection::ReadData() {
54 while (true) {
55 int rv = socket_->Read(read_buf_.get(), read_buf_->size(),
56 base::BindOnce(&Http1Connection::OnReadCompleted,
57 weak_factory_.GetWeakPtr()));
58 if (rv == ERR_IO_PENDING)
59 return;
60
61 if (HandleReadResult(rv)) {
62 return;
63 }
64 }
65 }
66
OnReadCompleted(int rv)67 void Http1Connection::OnReadCompleted(int rv) {
68 if (!HandleReadResult(rv))
69 ReadData();
70 }
71
HandleReadResult(int rv)72 bool Http1Connection::HandleReadResult(int rv) {
73 if (rv <= 0) {
74 server_delegate_->RemoveConnection(this);
75 return true;
76 }
77
78 if (connection_listener_)
79 connection_listener_->ReadFromSocket(*socket_, rv);
80
81 request_parser_.ProcessChunk(std::string_view(read_buf_->data(), rv));
82 if (request_parser_.ParseRequest() != HttpRequestParser::ACCEPTED)
83 return false;
84
85 std::unique_ptr<HttpRequest> request = request_parser_.GetRequest();
86
87 SSLInfo ssl_info;
88 if (socket_->GetSSLInfo(&ssl_info))
89 request->ssl_info = ssl_info;
90
91 server_delegate_->HandleRequest(weak_factory_.GetWeakPtr(),
92 std::move(request));
93 return true;
94 }
95
AddResponse(std::unique_ptr<HttpResponse> response)96 void Http1Connection::AddResponse(std::unique_ptr<HttpResponse> response) {
97 responses_.push_back(std::move(response));
98 }
99
SendResponseHeaders(HttpStatusCode status,const std::string & status_reason,const base::StringPairs & headers)100 void Http1Connection::SendResponseHeaders(HttpStatusCode status,
101 const std::string& status_reason,
102 const base::StringPairs& headers) {
103 std::string response_builder;
104
105 base::StringAppendF(&response_builder, "HTTP/1.1 %d %s\r\n", status,
106 status_reason.c_str());
107 for (const auto& header_pair : headers) {
108 const std::string& header_name = header_pair.first;
109 const std::string& header_value = header_pair.second;
110 base::StringAppendF(&response_builder, "%s: %s\r\n", header_name.c_str(),
111 header_value.c_str());
112 }
113
114 base::StringAppendF(&response_builder, "\r\n");
115 SendRawResponseHeaders(response_builder);
116 }
117
SendRawResponseHeaders(const std::string & headers)118 void Http1Connection::SendRawResponseHeaders(const std::string& headers) {
119 SendContents(headers, base::DoNothing());
120 }
121
SendContents(const std::string & contents,base::OnceClosure callback)122 void Http1Connection::SendContents(const std::string& contents,
123 base::OnceClosure callback) {
124 if (contents.empty()) {
125 std::move(callback).Run();
126 return;
127 }
128
129 scoped_refptr<DrainableIOBuffer> buf =
130 base::MakeRefCounted<DrainableIOBuffer>(
131 base::MakeRefCounted<StringIOBuffer>(contents), contents.length());
132
133 SendInternal(std::move(callback), buf);
134 }
135
FinishResponse()136 void Http1Connection::FinishResponse() {
137 server_delegate_->RemoveConnection(this, connection_listener_);
138 }
139
SendContentsAndFinish(const std::string & contents)140 void Http1Connection::SendContentsAndFinish(const std::string& contents) {
141 SendContents(contents, base::BindOnce(&HttpResponseDelegate::FinishResponse,
142 weak_factory_.GetWeakPtr()));
143 }
144
SendHeadersContentAndFinish(HttpStatusCode status,const std::string & status_reason,const base::StringPairs & headers,const std::string & contents)145 void Http1Connection::SendHeadersContentAndFinish(
146 HttpStatusCode status,
147 const std::string& status_reason,
148 const base::StringPairs& headers,
149 const std::string& contents) {
150 SendResponseHeaders(status, status_reason, headers);
151 SendContentsAndFinish(contents);
152 }
153
SendInternal(base::OnceClosure callback,scoped_refptr<DrainableIOBuffer> buf)154 void Http1Connection::SendInternal(base::OnceClosure callback,
155 scoped_refptr<DrainableIOBuffer> buf) {
156 while (buf->BytesRemaining() > 0) {
157 auto split_callback = base::SplitOnceCallback(std::move(callback));
158 callback = std::move(split_callback.first);
159 int rv =
160 socket_->Write(buf.get(), buf->BytesRemaining(),
161 base::BindOnce(&Http1Connection::OnSendInternalDone,
162 base::Unretained(this),
163 std::move(split_callback.second), buf),
164 TRAFFIC_ANNOTATION_FOR_TESTS);
165 if (rv == ERR_IO_PENDING)
166 return;
167
168 if (rv < 0)
169 break;
170 buf->DidConsume(rv);
171 }
172
173 // The Http1Connection will be deleted by the callback since we only need
174 // to serve a single request.
175 std::move(callback).Run();
176 }
177
OnSendInternalDone(base::OnceClosure callback,scoped_refptr<DrainableIOBuffer> buf,int rv)178 void Http1Connection::OnSendInternalDone(base::OnceClosure callback,
179 scoped_refptr<DrainableIOBuffer> buf,
180 int rv) {
181 if (rv < 0) {
182 std::move(callback).Run();
183 return;
184 }
185 buf->DidConsume(rv);
186 SendInternal(std::move(callback), buf);
187 }
188
189 } // namespace net::test_server
190