1 // Copyright 2012 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/http/http_stream_parser.h"
6
7 #include <stdint.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <string>
12 #include <string_view>
13 #include <utility>
14 #include <vector>
15
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_temp_dir.h"
19 #include "base/functional/bind.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/run_loop.h"
22 #include "base/task/single_thread_task_runner.h"
23 #include "base/test/task_environment.h"
24 #include "net/base/chunked_upload_data_stream.h"
25 #include "net/base/elements_upload_data_stream.h"
26 #include "net/base/io_buffer.h"
27 #include "net/base/load_flags.h"
28 #include "net/base/net_errors.h"
29 #include "net/base/test_completion_callback.h"
30 #include "net/base/upload_bytes_element_reader.h"
31 #include "net/base/upload_file_element_reader.h"
32 #include "net/http/http_connection_info.h"
33 #include "net/http/http_request_headers.h"
34 #include "net/http/http_request_info.h"
35 #include "net/http/http_response_headers.h"
36 #include "net/http/http_response_info.h"
37 #include "net/socket/socket_test_util.h"
38 #include "net/socket/stream_socket.h"
39 #include "net/test/gtest_util.h"
40 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
41 #include "testing/gmock/include/gmock/gmock.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43 #include "url/gurl.h"
44
45 using net::test::IsError;
46 using net::test::IsOk;
47
48 namespace net {
49
50 namespace {
51
52 const size_t kOutputSize = 1024; // Just large enough for this test.
53 // The number of bytes that can fit in a buffer of kOutputSize.
54 const size_t kMaxPayloadSize =
55 kOutputSize - HttpStreamParser::kChunkHeaderFooterSize;
56
57 // Helper method to create a connected ClientSocketHandle using |data|.
58 // Modifies |data|.
CreateConnectedSocket(SequencedSocketData * data)59 std::unique_ptr<StreamSocket> CreateConnectedSocket(SequencedSocketData* data) {
60 data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
61
62 auto socket =
63 std::make_unique<MockTCPClientSocket>(net::AddressList(), nullptr, data);
64
65 TestCompletionCallback callback;
66 EXPECT_THAT(socket->Connect(callback.callback()), IsOk());
67
68 return socket;
69 }
70
71 class ReadErrorUploadDataStream : public UploadDataStream {
72 public:
73 enum class FailureMode { SYNC, ASYNC };
74
ReadErrorUploadDataStream(FailureMode mode)75 explicit ReadErrorUploadDataStream(FailureMode mode)
76 : UploadDataStream(true, 0), async_(mode) {}
77
78 ReadErrorUploadDataStream(const ReadErrorUploadDataStream&) = delete;
79 ReadErrorUploadDataStream& operator=(const ReadErrorUploadDataStream&) =
80 delete;
81
82 private:
CompleteRead()83 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
84
85 // UploadDataStream implementation:
InitInternal(const NetLogWithSource & net_log)86 int InitInternal(const NetLogWithSource& net_log) override { return OK; }
87
ReadInternal(IOBuffer * buf,int buf_len)88 int ReadInternal(IOBuffer* buf, int buf_len) override {
89 if (async_ == FailureMode::ASYNC) {
90 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
91 FROM_HERE, base::BindOnce(&ReadErrorUploadDataStream::CompleteRead,
92 weak_factory_.GetWeakPtr()));
93 return ERR_IO_PENDING;
94 }
95 return ERR_FAILED;
96 }
97
ResetInternal()98 void ResetInternal() override {}
99
100 const FailureMode async_;
101
102 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_{this};
103 };
104
TEST(HttpStreamParser,DataReadErrorSynchronous)105 TEST(HttpStreamParser, DataReadErrorSynchronous) {
106 MockWrite writes[] = {
107 MockWrite(SYNCHRONOUS, 0, "POST / HTTP/1.1\r\n"),
108 MockWrite(SYNCHRONOUS, 1, "Content-Length: 12\r\n\r\n"),
109 };
110
111 SequencedSocketData data(base::span<MockRead>(), writes);
112 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
113
114 ReadErrorUploadDataStream upload_data_stream(
115 ReadErrorUploadDataStream::FailureMode::SYNC);
116
117 // Test upload progress before init.
118 UploadProgress progress = upload_data_stream.GetUploadProgress();
119 EXPECT_EQ(0u, progress.size());
120 EXPECT_EQ(0u, progress.position());
121
122 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
123 NetLogWithSource()),
124 IsOk());
125
126 // Test upload progress after init.
127 progress = upload_data_stream.GetUploadProgress();
128 EXPECT_EQ(0u, progress.size());
129 EXPECT_EQ(0u, progress.position());
130
131 HttpRequestInfo request;
132 request.method = "POST";
133 request.url = GURL("http://localhost");
134 request.upload_data_stream = &upload_data_stream;
135
136 scoped_refptr<GrowableIOBuffer> read_buffer =
137 base::MakeRefCounted<GrowableIOBuffer>();
138 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
139 read_buffer.get(), NetLogWithSource());
140
141 HttpRequestHeaders headers;
142 headers.SetHeader("Content-Length", "12");
143
144 HttpResponseInfo response;
145 TestCompletionCallback callback;
146 int result = parser.SendRequest("POST / HTTP/1.1\r\n", headers,
147 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
148 callback.callback());
149 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
150
151 progress = upload_data_stream.GetUploadProgress();
152 EXPECT_EQ(0u, progress.size());
153 EXPECT_EQ(0u, progress.position());
154
155 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
156 }
157
TEST(HttpStreamParser,DataReadErrorAsynchronous)158 TEST(HttpStreamParser, DataReadErrorAsynchronous) {
159 base::test::TaskEnvironment task_environment;
160
161 MockWrite writes[] = {
162 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"),
163 MockWrite(ASYNC, 1, "Content-Length: 12\r\n\r\n"),
164 };
165
166 SequencedSocketData data(base::span<MockRead>(), writes);
167 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
168
169 ReadErrorUploadDataStream upload_data_stream(
170 ReadErrorUploadDataStream::FailureMode::ASYNC);
171 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
172 NetLogWithSource()),
173 IsOk());
174
175 HttpRequestInfo request;
176 request.method = "POST";
177 request.url = GURL("http://localhost");
178 request.upload_data_stream = &upload_data_stream;
179
180 scoped_refptr<GrowableIOBuffer> read_buffer =
181 base::MakeRefCounted<GrowableIOBuffer>();
182 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
183 read_buffer.get(), NetLogWithSource());
184
185 HttpRequestHeaders headers;
186 headers.SetHeader("Content-Length", "12");
187
188 HttpResponseInfo response;
189 TestCompletionCallback callback;
190 int result = parser.SendRequest("POST / HTTP/1.1\r\n", headers,
191 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
192 callback.callback());
193 EXPECT_THAT(result, IsError(ERR_IO_PENDING));
194
195 UploadProgress progress = upload_data_stream.GetUploadProgress();
196 EXPECT_EQ(0u, progress.size());
197 EXPECT_EQ(0u, progress.position());
198
199 EXPECT_THAT(callback.GetResult(result), IsError(ERR_FAILED));
200
201 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
202 }
203
204 class InitAsyncUploadDataStream : public ChunkedUploadDataStream {
205 public:
InitAsyncUploadDataStream(int64_t identifier)206 explicit InitAsyncUploadDataStream(int64_t identifier)
207 : ChunkedUploadDataStream(identifier) {}
208
209 InitAsyncUploadDataStream(const InitAsyncUploadDataStream&) = delete;
210 InitAsyncUploadDataStream& operator=(const InitAsyncUploadDataStream&) =
211 delete;
212
213 private:
CompleteInit()214 void CompleteInit() { UploadDataStream::OnInitCompleted(OK); }
215
InitInternal(const NetLogWithSource & net_log)216 int InitInternal(const NetLogWithSource& net_log) override {
217 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
218 FROM_HERE, base::BindOnce(&InitAsyncUploadDataStream::CompleteInit,
219 weak_factory_.GetWeakPtr()));
220 return ERR_IO_PENDING;
221 }
222
223 base::WeakPtrFactory<InitAsyncUploadDataStream> weak_factory_{this};
224 };
225
TEST(HttpStreamParser,InitAsynchronousUploadDataStream)226 TEST(HttpStreamParser, InitAsynchronousUploadDataStream) {
227 base::test::TaskEnvironment task_environment;
228
229 InitAsyncUploadDataStream upload_data_stream(0);
230
231 TestCompletionCallback callback;
232 int result = upload_data_stream.Init(callback.callback(), NetLogWithSource());
233 ASSERT_THAT(result, IsError(ERR_IO_PENDING));
234
235 // Should be empty progress while initialization is in progress.
236 UploadProgress progress = upload_data_stream.GetUploadProgress();
237 EXPECT_EQ(0u, progress.size());
238 EXPECT_EQ(0u, progress.position());
239 EXPECT_THAT(callback.GetResult(result), IsOk());
240
241 // Initialization complete.
242 progress = upload_data_stream.GetUploadProgress();
243 EXPECT_EQ(0u, progress.size());
244 EXPECT_EQ(0u, progress.position());
245
246 HttpRequestInfo request;
247 request.method = "POST";
248 request.url = GURL("http://localhost");
249 request.upload_data_stream = &upload_data_stream;
250
251 static const char kChunk[] = "Chunk 1";
252 MockWrite writes[] = {
253 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"),
254 MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"),
255 MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"),
256 };
257
258 SequencedSocketData data(base::span<MockRead>(), writes);
259 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
260
261 scoped_refptr<GrowableIOBuffer> read_buffer =
262 base::MakeRefCounted<GrowableIOBuffer>();
263 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
264 read_buffer.get(), NetLogWithSource());
265
266 HttpRequestHeaders headers;
267 headers.SetHeader("Transfer-Encoding", "chunked");
268
269 HttpResponseInfo response;
270 TestCompletionCallback callback1;
271 int result1 = parser.SendRequest("POST / HTTP/1.1\r\n", headers,
272 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
273 callback1.callback());
274 EXPECT_EQ(ERR_IO_PENDING, result1);
275 base::RunLoop().RunUntilIdle();
276 upload_data_stream.AppendData(kChunk, std::size(kChunk) - 1, true);
277
278 // Check progress after read completes.
279 progress = upload_data_stream.GetUploadProgress();
280 EXPECT_EQ(0u, progress.size());
281 EXPECT_EQ(7u, progress.position());
282
283 // Check progress after reset.
284 upload_data_stream.Reset();
285 progress = upload_data_stream.GetUploadProgress();
286 EXPECT_EQ(0u, progress.size());
287 EXPECT_EQ(0u, progress.position());
288 }
289
290 // The empty payload is how the last chunk is encoded.
TEST(HttpStreamParser,EncodeChunk_EmptyPayload)291 TEST(HttpStreamParser, EncodeChunk_EmptyPayload) {
292 char output[kOutputSize];
293
294 const std::string_view kPayload = "";
295 const std::string_view kExpected = "0\r\n\r\n";
296 const int num_bytes_written =
297 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
298 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
299 EXPECT_EQ(kExpected, std::string_view(output, num_bytes_written));
300 }
301
TEST(HttpStreamParser,EncodeChunk_ShortPayload)302 TEST(HttpStreamParser, EncodeChunk_ShortPayload) {
303 char output[kOutputSize];
304
305 const std::string kPayload("foo\x00\x11\x22", 6);
306 // 11 = payload size + sizeof("6") + CRLF x 2.
307 const std::string kExpected("6\r\nfoo\x00\x11\x22\r\n", 11);
308 const int num_bytes_written =
309 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
310 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
311 EXPECT_EQ(kExpected, std::string_view(output, num_bytes_written));
312 }
313
TEST(HttpStreamParser,EncodeChunk_LargePayload)314 TEST(HttpStreamParser, EncodeChunk_LargePayload) {
315 char output[kOutputSize];
316
317 const std::string kPayload(1000, '\xff'); // '\xff' x 1000.
318 // 3E8 = 1000 in hex.
319 const std::string kExpected = "3E8\r\n" + kPayload + "\r\n";
320 const int num_bytes_written =
321 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
322 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
323 EXPECT_EQ(kExpected, std::string_view(output, num_bytes_written));
324 }
325
TEST(HttpStreamParser,EncodeChunk_FullPayload)326 TEST(HttpStreamParser, EncodeChunk_FullPayload) {
327 char output[kOutputSize];
328
329 const std::string kPayload(kMaxPayloadSize, '\xff');
330 // 3F4 = 1012 in hex.
331 const std::string kExpected = "3F4\r\n" + kPayload + "\r\n";
332 const int num_bytes_written =
333 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
334 ASSERT_EQ(kExpected.size(), static_cast<size_t>(num_bytes_written));
335 EXPECT_EQ(kExpected, std::string_view(output, num_bytes_written));
336 }
337
TEST(HttpStreamParser,EncodeChunk_TooLargePayload)338 TEST(HttpStreamParser, EncodeChunk_TooLargePayload) {
339 char output[kOutputSize];
340
341 // The payload is one byte larger the output buffer size.
342 const std::string kPayload(kMaxPayloadSize + 1, '\xff');
343 const int num_bytes_written =
344 HttpStreamParser::EncodeChunk(kPayload, output, sizeof(output));
345 ASSERT_THAT(num_bytes_written, IsError(ERR_INVALID_ARGUMENT));
346 }
347
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_NoBody)348 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_NoBody) {
349 // Shouldn't be merged if upload data is non-existent.
350 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody("some header",
351 nullptr));
352 }
353
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_EmptyBody)354 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) {
355 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
356 std::unique_ptr<UploadDataStream> body(
357 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
358 0));
359 ASSERT_THAT(body->Init(CompletionOnceCallback(), NetLogWithSource()), IsOk());
360 // Shouldn't be merged if upload data is empty.
361 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
362 "some header", body.get()));
363 }
364
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_ChunkedBody)365 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_ChunkedBody) {
366 const std::string payload = "123";
367 auto body = std::make_unique<ChunkedUploadDataStream>(0);
368 body->AppendData(payload.data(), payload.size(), true);
369 ASSERT_THAT(
370 body->Init(TestCompletionCallback().callback(), NetLogWithSource()),
371 IsOk());
372 // Shouldn't be merged if upload data carries chunked data.
373 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
374 "some header", body.get()));
375 }
376
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_FileBody)377 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) {
378 base::test::TaskEnvironment task_environment(
379 base::test::TaskEnvironment::MainThreadType::IO);
380
381 // Create an empty temporary file.
382 base::ScopedTempDir temp_dir;
383 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
384 base::FilePath temp_file_path;
385 ASSERT_TRUE(
386 base::CreateTemporaryFileInDir(temp_dir.GetPath(), &temp_file_path));
387
388 {
389 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
390
391 element_readers.push_back(std::make_unique<UploadFileElementReader>(
392 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
393 0, 0, base::Time()));
394
395 std::unique_ptr<UploadDataStream> body(
396 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
397 0));
398 TestCompletionCallback callback;
399 ASSERT_THAT(body->Init(callback.callback(), NetLogWithSource()),
400 IsError(ERR_IO_PENDING));
401 ASSERT_THAT(callback.WaitForResult(), IsOk());
402 // Shouldn't be merged if upload data carries a file, as it's not in-memory.
403 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
404 "some header", body.get()));
405 }
406
407 // UploadFileElementReaders may post clean-up tasks on destruction.
408 base::RunLoop().RunUntilIdle();
409 }
410
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_SmallBodyInMemory)411 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) {
412 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
413 const std::string payload = "123";
414 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
415 payload.data(), payload.size()));
416
417 std::unique_ptr<UploadDataStream> body(
418 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
419 0));
420 ASSERT_THAT(body->Init(CompletionOnceCallback(), NetLogWithSource()), IsOk());
421 // Yes, should be merged if the in-memory body is small here.
422 ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
423 "some header", body.get()));
424 }
425
TEST(HttpStreamParser,ShouldMergeRequestHeadersAndBody_LargeBodyInMemory)426 TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) {
427 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
428 const std::string payload(10000, 'a'); // 'a' x 10000.
429 element_readers.push_back(std::make_unique<UploadBytesElementReader>(
430 payload.data(), payload.size()));
431
432 std::unique_ptr<UploadDataStream> body(
433 std::make_unique<ElementsUploadDataStream>(std::move(element_readers),
434 0));
435 ASSERT_THAT(body->Init(CompletionOnceCallback(), NetLogWithSource()), IsOk());
436 // Shouldn't be merged if the in-memory body is large here.
437 ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
438 "some header", body.get()));
439 }
440
TEST(HttpStreamParser,SentBytesNoHeaders)441 TEST(HttpStreamParser, SentBytesNoHeaders) {
442 MockWrite writes[] = {
443 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"),
444 };
445
446 SequencedSocketData data(base::span<MockRead>(), writes);
447 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
448
449 HttpRequestInfo request;
450 request.method = "GET";
451 request.url = GURL("http://localhost");
452
453 scoped_refptr<GrowableIOBuffer> read_buffer =
454 base::MakeRefCounted<GrowableIOBuffer>();
455 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
456 read_buffer.get(), NetLogWithSource());
457
458 HttpResponseInfo response;
459 TestCompletionCallback callback;
460 EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
461 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
462 callback.callback()));
463
464 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
465 }
466
TEST(HttpStreamParser,SentBytesWithHeaders)467 TEST(HttpStreamParser, SentBytesWithHeaders) {
468 MockWrite writes[] = {
469 MockWrite(SYNCHRONOUS, 0,
470 "GET / HTTP/1.1\r\n"
471 "Host: localhost\r\n"
472 "Connection: Keep-Alive\r\n\r\n"),
473 };
474
475 SequencedSocketData data(base::span<MockRead>(), writes);
476 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
477
478 HttpRequestInfo request;
479 request.method = "GET";
480 request.url = GURL("http://localhost");
481
482 scoped_refptr<GrowableIOBuffer> read_buffer =
483 base::MakeRefCounted<GrowableIOBuffer>();
484 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
485 read_buffer.get(), NetLogWithSource());
486
487 HttpRequestHeaders headers;
488 headers.SetHeader("Host", "localhost");
489 headers.SetHeader("Connection", "Keep-Alive");
490
491 HttpResponseInfo response;
492 TestCompletionCallback callback;
493 EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers,
494 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
495 callback.callback()));
496
497 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
498 }
499
TEST(HttpStreamParser,SentBytesWithHeadersMultiWrite)500 TEST(HttpStreamParser, SentBytesWithHeadersMultiWrite) {
501 MockWrite writes[] = {
502 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
503 MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"),
504 MockWrite(SYNCHRONOUS, 2, "Connection: Keep-Alive\r\n\r\n"),
505 };
506
507 SequencedSocketData data(base::span<MockRead>(), writes);
508 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
509
510 HttpRequestInfo request;
511 request.method = "GET";
512 request.url = GURL("http://localhost");
513
514 scoped_refptr<GrowableIOBuffer> read_buffer =
515 base::MakeRefCounted<GrowableIOBuffer>();
516 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
517 read_buffer.get(), NetLogWithSource());
518
519 HttpRequestHeaders headers;
520 headers.SetHeader("Host", "localhost");
521 headers.SetHeader("Connection", "Keep-Alive");
522
523 HttpResponseInfo response;
524 TestCompletionCallback callback;
525
526 EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers,
527 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
528 callback.callback()));
529
530 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
531 }
532
TEST(HttpStreamParser,SentBytesWithErrorWritingHeaders)533 TEST(HttpStreamParser, SentBytesWithErrorWritingHeaders) {
534 MockWrite writes[] = {
535 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
536 MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"),
537 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 2),
538 };
539
540 SequencedSocketData data(base::span<MockRead>(), writes);
541 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
542
543 HttpRequestInfo request;
544 request.method = "GET";
545 request.url = GURL("http://localhost");
546
547 scoped_refptr<GrowableIOBuffer> read_buffer =
548 base::MakeRefCounted<GrowableIOBuffer>();
549 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
550 read_buffer.get(), NetLogWithSource());
551
552 HttpRequestHeaders headers;
553 headers.SetHeader("Host", "localhost");
554 headers.SetHeader("Connection", "Keep-Alive");
555
556 HttpResponseInfo response;
557 TestCompletionCallback callback;
558 EXPECT_EQ(ERR_CONNECTION_RESET,
559 parser.SendRequest("GET / HTTP/1.1\r\n", headers,
560 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
561 callback.callback()));
562
563 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
564 }
565
TEST(HttpStreamParser,SentBytesPost)566 TEST(HttpStreamParser, SentBytesPost) {
567 MockWrite writes[] = {
568 MockWrite(SYNCHRONOUS, 0, "POST / HTTP/1.1\r\n"),
569 MockWrite(SYNCHRONOUS, 1, "Content-Length: 12\r\n\r\n"),
570 MockWrite(SYNCHRONOUS, 2, "hello world!"),
571 };
572
573 SequencedSocketData data(base::span<MockRead>(), writes);
574 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
575
576 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
577 element_readers.push_back(
578 std::make_unique<UploadBytesElementReader>("hello world!", 12));
579 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
580 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
581 NetLogWithSource()),
582 IsOk());
583
584 HttpRequestInfo request;
585 request.method = "POST";
586 request.url = GURL("http://localhost");
587 request.upload_data_stream = &upload_data_stream;
588
589 scoped_refptr<GrowableIOBuffer> read_buffer =
590 base::MakeRefCounted<GrowableIOBuffer>();
591 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
592 read_buffer.get(), NetLogWithSource());
593
594 HttpRequestHeaders headers;
595 headers.SetHeader("Content-Length", "12");
596
597 HttpResponseInfo response;
598 TestCompletionCallback callback;
599 EXPECT_EQ(OK, parser.SendRequest("POST / HTTP/1.1\r\n", headers,
600 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
601 callback.callback()));
602
603 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
604
605 UploadProgress progress = upload_data_stream.GetUploadProgress();
606 EXPECT_EQ(12u, progress.size());
607 EXPECT_EQ(12u, progress.position());
608 }
609
TEST(HttpStreamParser,SentBytesChunkedPostError)610 TEST(HttpStreamParser, SentBytesChunkedPostError) {
611 base::test::TaskEnvironment task_environment;
612
613 static const char kChunk[] = "Chunk 1";
614
615 MockWrite writes[] = {
616 MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"),
617 MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"),
618 MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"),
619 MockWrite(SYNCHRONOUS, ERR_FAILED, 3),
620 };
621
622 SequencedSocketData data(base::span<MockRead>(), writes);
623 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
624
625 ChunkedUploadDataStream upload_data_stream(0);
626 ASSERT_THAT(upload_data_stream.Init(TestCompletionCallback().callback(),
627 NetLogWithSource()),
628 IsOk());
629
630 HttpRequestInfo request;
631 request.method = "POST";
632 request.url = GURL("http://localhost");
633 request.upload_data_stream = &upload_data_stream;
634
635 scoped_refptr<GrowableIOBuffer> read_buffer =
636 base::MakeRefCounted<GrowableIOBuffer>();
637 HttpStreamParser parser(stream_socket.get(), false /* is_reused */, &request,
638 read_buffer.get(), NetLogWithSource());
639
640 HttpRequestHeaders headers;
641 headers.SetHeader("Transfer-Encoding", "chunked");
642
643 HttpResponseInfo response;
644 TestCompletionCallback callback;
645 EXPECT_EQ(ERR_IO_PENDING, parser.SendRequest("POST / HTTP/1.1\r\n", headers,
646 TRAFFIC_ANNOTATION_FOR_TESTS,
647 &response, callback.callback()));
648
649 base::RunLoop().RunUntilIdle();
650 upload_data_stream.AppendData(kChunk, std::size(kChunk) - 1, false);
651
652 base::RunLoop().RunUntilIdle();
653 // This write should fail.
654 upload_data_stream.AppendData(kChunk, std::size(kChunk) - 1, false);
655 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
656
657 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
658
659 UploadProgress progress = upload_data_stream.GetUploadProgress();
660 EXPECT_EQ(0u, progress.size());
661 EXPECT_EQ(14u, progress.position());
662 }
663
664 // Test to ensure the HttpStreamParser state machine does not get confused
665 // when sending a request with a chunked body with only one chunk that becomes
666 // available asynchronously.
TEST(HttpStreamParser,AsyncSingleChunkAndAsyncSocket)667 TEST(HttpStreamParser, AsyncSingleChunkAndAsyncSocket) {
668 base::test::TaskEnvironment task_environment;
669
670 static const char kChunk[] = "Chunk";
671
672 MockWrite writes[] = {
673 MockWrite(ASYNC, 0,
674 "GET /one.html HTTP/1.1\r\n"
675 "Transfer-Encoding: chunked\r\n\r\n"),
676 MockWrite(ASYNC, 1, "5\r\nChunk\r\n"),
677 MockWrite(ASYNC, 2, "0\r\n\r\n"),
678 };
679
680 // The size of the response body, as reflected in the Content-Length of the
681 // MockRead below.
682 static const int kBodySize = 8;
683
684 MockRead reads[] = {
685 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n"),
686 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"),
687 MockRead(ASYNC, 5, "one.html"),
688 MockRead(SYNCHRONOUS, 0, 6), // EOF
689 };
690
691 ChunkedUploadDataStream upload_stream(0);
692 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
693 NetLogWithSource()),
694 IsOk());
695
696 SequencedSocketData data(reads, writes);
697 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
698
699 HttpRequestInfo request_info;
700 request_info.method = "GET";
701 request_info.url = GURL("http://localhost");
702 request_info.upload_data_stream = &upload_stream;
703
704 scoped_refptr<GrowableIOBuffer> read_buffer =
705 base::MakeRefCounted<GrowableIOBuffer>();
706 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
707 &request_info, read_buffer.get(), NetLogWithSource());
708
709 HttpRequestHeaders request_headers;
710 request_headers.SetHeader("Transfer-Encoding", "chunked");
711
712 HttpResponseInfo response_info;
713 TestCompletionCallback callback;
714 // This will attempt to Write() the initial request and headers, which will
715 // complete asynchronously.
716 ASSERT_EQ(ERR_IO_PENDING,
717 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
718 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
719 callback.callback()));
720
721 // Complete the initial request write. Callback should not have been invoked.
722 base::RunLoop().RunUntilIdle();
723 ASSERT_FALSE(callback.have_result());
724
725 // Now append the only chunk and wait for the callback.
726 upload_stream.AppendData(kChunk, std::size(kChunk) - 1, true);
727 ASSERT_THAT(callback.WaitForResult(), IsOk());
728
729 // Attempt to read the response status and the response headers.
730 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
731 IsError(ERR_IO_PENDING));
732 ASSERT_THAT(callback.WaitForResult(), IsOk());
733
734 // Finally, attempt to read the response body.
735 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
736 ASSERT_EQ(ERR_IO_PENDING,
737 parser.ReadResponseBody(body_buffer.get(), kBodySize,
738 callback.callback()));
739 ASSERT_EQ(kBodySize, callback.WaitForResult());
740
741 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
742 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
743 }
744
745 // Test to ensure the HttpStreamParser state machine does not get confused
746 // when sending a request with a chunked body with only one chunk that is
747 // available synchronously.
TEST(HttpStreamParser,SyncSingleChunkAndAsyncSocket)748 TEST(HttpStreamParser, SyncSingleChunkAndAsyncSocket) {
749 base::test::TaskEnvironment task_environment;
750
751 static const char kChunk[] = "Chunk";
752
753 MockWrite writes[] = {
754 MockWrite(ASYNC, 0,
755 "GET /one.html HTTP/1.1\r\n"
756 "Transfer-Encoding: chunked\r\n\r\n"),
757 MockWrite(ASYNC, 1, "5\r\nChunk\r\n"),
758 MockWrite(ASYNC, 2, "0\r\n\r\n"),
759 };
760
761 // The size of the response body, as reflected in the Content-Length of the
762 // MockRead below.
763 static const int kBodySize = 8;
764
765 MockRead reads[] = {
766 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n"),
767 MockRead(ASYNC, 4, "Content-Length: 8\r\n\r\n"),
768 MockRead(ASYNC, 5, "one.html"),
769 MockRead(SYNCHRONOUS, 0, 6), // EOF
770 };
771
772 ChunkedUploadDataStream upload_stream(0);
773 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
774 NetLogWithSource()),
775 IsOk());
776 // Append the only chunk.
777 upload_stream.AppendData(kChunk, std::size(kChunk) - 1, true);
778
779 SequencedSocketData data(reads, writes);
780 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
781
782 HttpRequestInfo request_info;
783 request_info.method = "GET";
784 request_info.url = GURL("http://localhost");
785 request_info.upload_data_stream = &upload_stream;
786
787 scoped_refptr<GrowableIOBuffer> read_buffer =
788 base::MakeRefCounted<GrowableIOBuffer>();
789 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
790 &request_info, read_buffer.get(), NetLogWithSource());
791
792 HttpRequestHeaders request_headers;
793 request_headers.SetHeader("Transfer-Encoding", "chunked");
794
795 HttpResponseInfo response_info;
796 TestCompletionCallback callback;
797 // This will attempt to Write() the initial request and headers, which will
798 // complete asynchronously.
799 ASSERT_EQ(ERR_IO_PENDING,
800 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
801 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
802 callback.callback()));
803 ASSERT_THAT(callback.WaitForResult(), IsOk());
804
805 // Attempt to read the response status and the response headers.
806 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
807 IsError(ERR_IO_PENDING));
808 ASSERT_THAT(callback.WaitForResult(), IsOk());
809
810 // Finally, attempt to read the response body.
811 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
812 ASSERT_EQ(ERR_IO_PENDING,
813 parser.ReadResponseBody(body_buffer.get(), kBodySize,
814 callback.callback()));
815 ASSERT_EQ(kBodySize, callback.WaitForResult());
816
817 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
818 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
819 }
820
821 // Test to ensure the HttpStreamParser state machine does not get confused
822 // when sending a request with a chunked body, where chunks become available
823 // asynchronously, over a socket where writes may also complete
824 // asynchronously.
825 // This is a regression test for http://crbug.com/132243
TEST(HttpStreamParser,AsyncChunkAndAsyncSocketWithMultipleChunks)826 TEST(HttpStreamParser, AsyncChunkAndAsyncSocketWithMultipleChunks) {
827 base::test::TaskEnvironment task_environment;
828
829 // The chunks that will be written in the request, as reflected in the
830 // MockWrites below.
831 static const char kChunk1[] = "Chunk 1";
832 static const char kChunk2[] = "Chunky 2";
833 static const char kChunk3[] = "Test 3";
834
835 MockWrite writes[] = {
836 MockWrite(ASYNC, 0,
837 "GET /one.html HTTP/1.1\r\n"
838 "Transfer-Encoding: chunked\r\n\r\n"),
839 MockWrite(ASYNC, 1, "7\r\nChunk 1\r\n"),
840 MockWrite(ASYNC, 2, "8\r\nChunky 2\r\n"),
841 MockWrite(ASYNC, 3, "6\r\nTest 3\r\n"),
842 MockWrite(ASYNC, 4, "0\r\n\r\n"),
843 };
844
845 // The size of the response body, as reflected in the Content-Length of the
846 // MockRead below.
847 static const int kBodySize = 8;
848
849 MockRead reads[] = {
850 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\n"),
851 MockRead(ASYNC, 6, "Content-Length: 8\r\n\r\n"),
852 MockRead(ASYNC, 7, "one.html"),
853 MockRead(SYNCHRONOUS, 0, 8), // EOF
854 };
855
856 ChunkedUploadDataStream upload_stream(0);
857 upload_stream.AppendData(kChunk1, std::size(kChunk1) - 1, false);
858 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
859 NetLogWithSource()),
860 IsOk());
861
862 SequencedSocketData data(reads, writes);
863 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
864
865 HttpRequestInfo request_info;
866 request_info.method = "GET";
867 request_info.url = GURL("http://localhost");
868 request_info.upload_data_stream = &upload_stream;
869
870 scoped_refptr<GrowableIOBuffer> read_buffer =
871 base::MakeRefCounted<GrowableIOBuffer>();
872 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
873 &request_info, read_buffer.get(), NetLogWithSource());
874
875 HttpRequestHeaders request_headers;
876 request_headers.SetHeader("Transfer-Encoding", "chunked");
877
878 HttpResponseInfo response_info;
879 TestCompletionCallback callback;
880 // This will attempt to Write() the initial request and headers, which will
881 // complete asynchronously.
882 ASSERT_EQ(ERR_IO_PENDING,
883 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
884 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
885 callback.callback()));
886 ASSERT_FALSE(callback.have_result());
887
888 // Sending the request and the first chunk completes.
889 base::RunLoop().RunUntilIdle();
890 ASSERT_FALSE(callback.have_result());
891
892 // Now append another chunk.
893 upload_stream.AppendData(kChunk2, std::size(kChunk2) - 1, false);
894 ASSERT_FALSE(callback.have_result());
895
896 // Add the final chunk, while the write for the second is still pending,
897 // which should not confuse the state machine.
898 upload_stream.AppendData(kChunk3, std::size(kChunk3) - 1, true);
899 ASSERT_FALSE(callback.have_result());
900
901 // Wait for writes to complete.
902 ASSERT_THAT(callback.WaitForResult(), IsOk());
903
904 // Attempt to read the response status and the response headers.
905 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
906 IsError(ERR_IO_PENDING));
907 ASSERT_THAT(callback.WaitForResult(), IsOk());
908
909 // Finally, attempt to read the response body.
910 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
911 ASSERT_EQ(ERR_IO_PENDING,
912 parser.ReadResponseBody(body_buffer.get(), kBodySize,
913 callback.callback()));
914 ASSERT_EQ(kBodySize, callback.WaitForResult());
915
916 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
917 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
918 }
919
920 // Test to ensure the HttpStreamParser state machine does not get confused
921 // when there's only one "chunk" with 0 bytes, and is received from the
922 // UploadStream only after sending the request headers successfully.
TEST(HttpStreamParser,AsyncEmptyChunkedUpload)923 TEST(HttpStreamParser, AsyncEmptyChunkedUpload) {
924 base::test::TaskEnvironment task_environment;
925
926 MockWrite writes[] = {
927 MockWrite(ASYNC, 0,
928 "GET /one.html HTTP/1.1\r\n"
929 "Transfer-Encoding: chunked\r\n\r\n"),
930 MockWrite(ASYNC, 1, "0\r\n\r\n"),
931 };
932
933 // The size of the response body, as reflected in the Content-Length of the
934 // MockRead below.
935 const int kBodySize = 8;
936
937 MockRead reads[] = {
938 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"),
939 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"),
940 MockRead(ASYNC, 4, "one.html"),
941 MockRead(SYNCHRONOUS, 0, 5), // EOF
942 };
943
944 ChunkedUploadDataStream upload_stream(0);
945 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
946 NetLogWithSource()),
947 IsOk());
948
949 SequencedSocketData data(reads, writes);
950 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
951
952 HttpRequestInfo request_info;
953 request_info.method = "GET";
954 request_info.url = GURL("http://localhost");
955 request_info.upload_data_stream = &upload_stream;
956
957 scoped_refptr<GrowableIOBuffer> read_buffer =
958 base::MakeRefCounted<GrowableIOBuffer>();
959 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
960 &request_info, read_buffer.get(), NetLogWithSource());
961
962 HttpRequestHeaders request_headers;
963 request_headers.SetHeader("Transfer-Encoding", "chunked");
964
965 HttpResponseInfo response_info;
966 TestCompletionCallback callback;
967 // This will attempt to Write() the initial request and headers, which will
968 // complete asynchronously.
969 ASSERT_EQ(ERR_IO_PENDING,
970 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
971 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
972 callback.callback()));
973
974 // Now append the terminal 0-byte "chunk".
975 upload_stream.AppendData(nullptr, 0, true);
976 ASSERT_FALSE(callback.have_result());
977
978 ASSERT_THAT(callback.WaitForResult(), IsOk());
979
980 // Attempt to read the response status and the response headers.
981 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
982 IsError(ERR_IO_PENDING));
983 ASSERT_THAT(callback.WaitForResult(), IsOk());
984
985 // Finally, attempt to read the response body.
986 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
987 ASSERT_EQ(ERR_IO_PENDING,
988 parser.ReadResponseBody(body_buffer.get(), kBodySize,
989 callback.callback()));
990 ASSERT_EQ(kBodySize, callback.WaitForResult());
991
992 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
993 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
994 }
995
996 // Test to ensure the HttpStreamParser state machine does not get confused
997 // when there's only one "chunk" with 0 bytes, which was already appended before
998 // the request was started.
TEST(HttpStreamParser,SyncEmptyChunkedUpload)999 TEST(HttpStreamParser, SyncEmptyChunkedUpload) {
1000 base::test::TaskEnvironment task_environment;
1001
1002 MockWrite writes[] = {
1003 MockWrite(ASYNC, 0,
1004 "GET /one.html HTTP/1.1\r\n"
1005 "Transfer-Encoding: chunked\r\n\r\n"),
1006 MockWrite(ASYNC, 1, "0\r\n\r\n"),
1007 };
1008
1009 // The size of the response body, as reflected in the Content-Length of the
1010 // MockRead below.
1011 const int kBodySize = 8;
1012
1013 MockRead reads[] = {
1014 MockRead(ASYNC, 2, "HTTP/1.1 200 OK\r\n"),
1015 MockRead(ASYNC, 3, "Content-Length: 8\r\n\r\n"),
1016 MockRead(ASYNC, 4, "one.html"),
1017 MockRead(SYNCHRONOUS, 0, 5), // EOF
1018 };
1019
1020 ChunkedUploadDataStream upload_stream(0);
1021 ASSERT_THAT(upload_stream.Init(TestCompletionCallback().callback(),
1022 NetLogWithSource()),
1023 IsOk());
1024 // Append final empty chunk.
1025 upload_stream.AppendData(nullptr, 0, true);
1026
1027 SequencedSocketData data(reads, writes);
1028 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
1029
1030 HttpRequestInfo request_info;
1031 request_info.method = "GET";
1032 request_info.url = GURL("http://localhost");
1033 request_info.upload_data_stream = &upload_stream;
1034
1035 scoped_refptr<GrowableIOBuffer> read_buffer =
1036 base::MakeRefCounted<GrowableIOBuffer>();
1037 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
1038 &request_info, read_buffer.get(), NetLogWithSource());
1039
1040 HttpRequestHeaders request_headers;
1041 request_headers.SetHeader("Transfer-Encoding", "chunked");
1042
1043 HttpResponseInfo response_info;
1044 TestCompletionCallback callback;
1045 // This will attempt to Write() the initial request and headers, which will
1046 // complete asynchronously.
1047 ASSERT_EQ(ERR_IO_PENDING,
1048 parser.SendRequest("GET /one.html HTTP/1.1\r\n", request_headers,
1049 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
1050 callback.callback()));
1051
1052 // Complete writing the request headers and body.
1053 ASSERT_THAT(callback.WaitForResult(), IsOk());
1054
1055 // Attempt to read the response status and the response headers.
1056 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()),
1057 IsError(ERR_IO_PENDING));
1058 ASSERT_THAT(callback.WaitForResult(), IsOk());
1059
1060 // Finally, attempt to read the response body.
1061 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
1062 ASSERT_EQ(ERR_IO_PENDING,
1063 parser.ReadResponseBody(body_buffer.get(), kBodySize,
1064 callback.callback()));
1065 ASSERT_EQ(kBodySize, callback.WaitForResult());
1066
1067 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
1068 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
1069 }
1070
TEST(HttpStreamParser,TruncatedHeaders)1071 TEST(HttpStreamParser, TruncatedHeaders) {
1072 MockRead truncated_status_reads[] = {
1073 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 20"),
1074 MockRead(SYNCHRONOUS, 0, 2), // EOF
1075 };
1076
1077 MockRead truncated_after_status_reads[] = {
1078 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\n"),
1079 MockRead(SYNCHRONOUS, 0, 2), // EOF
1080 };
1081
1082 MockRead truncated_in_header_reads[] = {
1083 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHead"),
1084 MockRead(SYNCHRONOUS, 0, 2), // EOF
1085 };
1086
1087 MockRead truncated_after_header_reads[] = {
1088 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n"),
1089 MockRead(SYNCHRONOUS, 0, 2), // EOF
1090 };
1091
1092 MockRead truncated_after_final_newline_reads[] = {
1093 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r"),
1094 MockRead(SYNCHRONOUS, 0, 2), // EOF
1095 };
1096
1097 MockRead not_truncated_reads[] = {
1098 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Ok\r\nHeader: foo\r\n\r\n"),
1099 MockRead(SYNCHRONOUS, 0, 2), // EOF
1100 };
1101
1102 base::span<MockRead> reads[] = {
1103 truncated_status_reads,
1104 truncated_after_status_reads,
1105 truncated_in_header_reads,
1106 truncated_after_header_reads,
1107 truncated_after_final_newline_reads,
1108 not_truncated_reads,
1109 };
1110
1111 MockWrite writes[] = {
1112 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"),
1113 };
1114
1115 enum {
1116 HTTP = 0,
1117 HTTPS,
1118 NUM_PROTOCOLS,
1119 };
1120
1121 for (size_t protocol = 0; protocol < NUM_PROTOCOLS; protocol++) {
1122 SCOPED_TRACE(protocol);
1123
1124 for (size_t i = 0; i < std::size(reads); i++) {
1125 SCOPED_TRACE(i);
1126 SequencedSocketData data(reads[i], writes);
1127 std::unique_ptr<StreamSocket> stream_socket(CreateConnectedSocket(&data));
1128
1129 HttpRequestInfo request_info;
1130 request_info.method = "GET";
1131 if (protocol == HTTP) {
1132 request_info.url = GURL("http://localhost");
1133 } else {
1134 request_info.url = GURL("https://localhost");
1135 }
1136 request_info.load_flags = LOAD_NORMAL;
1137
1138 scoped_refptr<GrowableIOBuffer> read_buffer =
1139 base::MakeRefCounted<GrowableIOBuffer>();
1140 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
1141 &request_info, read_buffer.get(),
1142 NetLogWithSource());
1143
1144 HttpRequestHeaders request_headers;
1145 HttpResponseInfo response_info;
1146 TestCompletionCallback callback;
1147 ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", request_headers,
1148 TRAFFIC_ANNOTATION_FOR_TESTS,
1149 &response_info, callback.callback()));
1150
1151 int rv = parser.ReadResponseHeaders(callback.callback());
1152 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
1153 if (i == std::size(reads) - 1) {
1154 EXPECT_THAT(rv, IsOk());
1155 EXPECT_TRUE(response_info.headers.get());
1156 EXPECT_EQ(CountReadBytes(reads[i]), parser.received_bytes());
1157 } else {
1158 if (protocol == HTTP) {
1159 EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
1160 EXPECT_TRUE(response_info.headers.get());
1161 EXPECT_EQ(CountReadBytes(reads[i]), parser.received_bytes());
1162 } else {
1163 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TRUNCATED));
1164 EXPECT_FALSE(response_info.headers.get());
1165 EXPECT_EQ(0, parser.received_bytes());
1166 }
1167 }
1168 }
1169 }
1170 }
1171
1172 // Confirm that on 101 response, the headers are parsed but the data that
1173 // follows remains in the buffer.
TEST(HttpStreamParser,WebSocket101Response)1174 TEST(HttpStreamParser, WebSocket101Response) {
1175 MockRead reads[] = {
1176 MockRead(SYNCHRONOUS, 1,
1177 "HTTP/1.1 101 Switching Protocols\r\n"
1178 "Upgrade: websocket\r\n"
1179 "Connection: Upgrade\r\n"
1180 "\r\n"
1181 "a fake websocket frame"),
1182 };
1183
1184 MockWrite writes[] = {
1185 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"),
1186 };
1187
1188 SequencedSocketData data(reads, writes);
1189 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
1190
1191 HttpRequestInfo request_info;
1192 request_info.method = "GET";
1193 request_info.url = GURL("http://localhost");
1194 request_info.load_flags = LOAD_NORMAL;
1195
1196 scoped_refptr<GrowableIOBuffer> read_buffer =
1197 base::MakeRefCounted<GrowableIOBuffer>();
1198 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
1199 &request_info, read_buffer.get(), NetLogWithSource());
1200
1201 HttpRequestHeaders request_headers;
1202 HttpResponseInfo response_info;
1203 TestCompletionCallback callback;
1204 ASSERT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", request_headers,
1205 TRAFFIC_ANNOTATION_FOR_TESTS, &response_info,
1206 callback.callback()));
1207
1208 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()), IsOk());
1209 ASSERT_TRUE(response_info.headers.get());
1210 EXPECT_EQ(101, response_info.headers->response_code());
1211 EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade"));
1212 EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket"));
1213 EXPECT_EQ(read_buffer->capacity(), read_buffer->offset());
1214 EXPECT_EQ(
1215 "a fake websocket frame",
1216 std::string_view(read_buffer->StartOfBuffer(), read_buffer->capacity()));
1217
1218 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
1219 EXPECT_EQ(CountReadBytes(reads) -
1220 static_cast<int64_t>(strlen("a fake websocket frame")),
1221 parser.received_bytes());
1222 }
1223
1224 // Helper class for constructing HttpStreamParser and running GET requests.
1225 class SimpleGetRunner {
1226 public:
SimpleGetRunner()1227 SimpleGetRunner()
1228 : url_("http://localhost"),
1229 read_buffer_(base::MakeRefCounted<GrowableIOBuffer>()) {
1230 writes_.emplace_back(
1231 MockWrite(SYNCHRONOUS, sequence_number_++, "GET / HTTP/1.1\r\n\r\n"));
1232 }
1233
set_url(const GURL & url)1234 void set_url(const GURL& url) { url_ = url; }
1235
parser()1236 HttpStreamParser* parser() { return parser_.get(); }
read_buffer()1237 GrowableIOBuffer* read_buffer() { return read_buffer_.get(); }
response_info()1238 HttpResponseInfo* response_info() { return &response_info_; }
1239
AddInitialData(const std::string & data)1240 void AddInitialData(const std::string& data) {
1241 int offset = read_buffer_->offset();
1242 int size = data.size();
1243 read_buffer_->SetCapacity(offset + size);
1244 memcpy(read_buffer_->StartOfBuffer() + offset, data.data(), size);
1245 read_buffer_->set_offset(offset + size);
1246 }
1247
1248 // The data used to back |string_piece| must stay alive until all mock data
1249 // has been read.
AddRead(std::string_view string_piece)1250 void AddRead(std::string_view string_piece) {
1251 reads_.emplace_back(SYNCHRONOUS, string_piece.data(), string_piece.length(),
1252 sequence_number_++);
1253 }
1254
AddAsyncRead(std::string_view string_piece)1255 void AddAsyncRead(std::string_view string_piece) {
1256 reads_.emplace_back(ASYNC, string_piece.data(), string_piece.length(),
1257 sequence_number_++);
1258 }
1259
SetupParserAndSendRequest()1260 void SetupParserAndSendRequest() {
1261 reads_.emplace_back(SYNCHRONOUS, 0, sequence_number_++); // EOF
1262
1263 data_ = std::make_unique<SequencedSocketData>(reads_, writes_);
1264 stream_socket_ = CreateConnectedSocket(data_.get());
1265
1266 request_info_.method = "GET";
1267 request_info_.url = url_;
1268 request_info_.load_flags = LOAD_NORMAL;
1269
1270 parser_ = std::make_unique<HttpStreamParser>(
1271 stream_socket_.get(), false /* is_reused */, &request_info_,
1272 read_buffer(), NetLogWithSource());
1273
1274 TestCompletionCallback callback;
1275 ASSERT_EQ(OK, parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_,
1276 TRAFFIC_ANNOTATION_FOR_TESTS,
1277 &response_info_, callback.callback()));
1278 }
1279
ReadHeadersExpectingError(Error error)1280 void ReadHeadersExpectingError(Error error) {
1281 TestCompletionCallback callback;
1282 EXPECT_THAT(parser_->ReadResponseHeaders(callback.callback()),
1283 IsError(error));
1284 }
1285
ReadHeaders()1286 void ReadHeaders() { ReadHeadersExpectingError(OK); }
1287
ReadBody(int user_buf_len,int * read_lengths)1288 std::string ReadBody(int user_buf_len, int* read_lengths) {
1289 TestCompletionCallback callback;
1290 auto buffer = base::MakeRefCounted<IOBufferWithSize>(user_buf_len);
1291 int rv;
1292 int i = 0;
1293 std::string body;
1294 while (true) {
1295 rv = parser_->ReadResponseBody(
1296 buffer.get(), user_buf_len, callback.callback());
1297 EXPECT_EQ(read_lengths[i], rv);
1298 if (rv == ERR_IO_PENDING) {
1299 rv = callback.WaitForResult();
1300 i++;
1301 EXPECT_EQ(read_lengths[i], rv);
1302 }
1303 if (rv > 0)
1304 body.append(buffer->data(), rv);
1305 i++;
1306 if (rv <= 0)
1307 return body;
1308 }
1309 }
1310
1311 private:
1312 GURL url_;
1313
1314 HttpRequestHeaders request_headers_;
1315 HttpResponseInfo response_info_;
1316 HttpRequestInfo request_info_;
1317 scoped_refptr<GrowableIOBuffer> read_buffer_;
1318 std::vector<MockRead> reads_;
1319 std::vector<MockWrite> writes_;
1320 std::unique_ptr<StreamSocket> stream_socket_;
1321 std::unique_ptr<SequencedSocketData> data_;
1322 std::unique_ptr<HttpStreamParser> parser_;
1323 int sequence_number_ = 0;
1324 };
1325
1326 // Test that HTTP/0.9 works as expected, only on ports where it should be
1327 // enabled.
TEST(HttpStreamParser,Http09PortTests)1328 TEST(HttpStreamParser, Http09PortTests) {
1329 struct TestCase {
1330 const char* url;
1331
1332 // Expected result when trying to read headers and response is an HTTP/0.9
1333 // non-Shoutcast response.
1334 Error expected_09_header_error;
1335
1336 // Expected result when trying to read headers for a shoutcast response.
1337 Error expected_shoutcast_header_error;
1338 };
1339
1340 const TestCase kTestCases[] = {
1341 // Default ports should work for HTTP/0.9, regardless of whether the port
1342 // is explicitly specified or not.
1343 {"http://foo.com/", OK, OK},
1344 {"http://foo.com:80/", OK, OK},
1345 {"https://foo.com/", OK, OK},
1346 {"https://foo.com:443/", OK, OK},
1347
1348 // Non-standard ports should not support HTTP/0.9, by default.
1349 {"http://foo.com:8080/", ERR_INVALID_HTTP_RESPONSE, OK},
1350 {"https://foo.com:8080/", ERR_INVALID_HTTP_RESPONSE,
1351 ERR_INVALID_HTTP_RESPONSE},
1352 {"http://foo.com:443/", ERR_INVALID_HTTP_RESPONSE, OK},
1353 {"https://foo.com:80/", ERR_INVALID_HTTP_RESPONSE,
1354 ERR_INVALID_HTTP_RESPONSE},
1355 };
1356
1357 const std::string kResponse = "hello\r\nworld\r\n";
1358
1359 for (const auto& test_case : kTestCases) {
1360 SimpleGetRunner get_runner;
1361 get_runner.set_url(GURL(test_case.url));
1362 get_runner.AddRead(kResponse);
1363 get_runner.SetupParserAndSendRequest();
1364
1365 get_runner.ReadHeadersExpectingError(test_case.expected_09_header_error);
1366 if (test_case.expected_09_header_error != OK)
1367 continue;
1368
1369 ASSERT_TRUE(get_runner.response_info()->headers);
1370 EXPECT_EQ("HTTP/0.9 200 OK",
1371 get_runner.response_info()->headers->GetStatusLine());
1372
1373 EXPECT_EQ(0, get_runner.parser()->received_bytes());
1374 int read_lengths[] = {static_cast<int>(kResponse.size()), 0};
1375 get_runner.ReadBody(kResponse.size(), read_lengths);
1376 EXPECT_EQ(kResponse.size(),
1377 static_cast<size_t>(get_runner.parser()->received_bytes()));
1378 EXPECT_EQ(HttpConnectionInfo::kHTTP0_9,
1379 get_runner.response_info()->connection_info);
1380 }
1381
1382 const std::string kShoutcastResponse = "ICY 200 blah\r\n\r\n";
1383 for (const auto& test_case : kTestCases) {
1384 SimpleGetRunner get_runner;
1385 get_runner.set_url(GURL(test_case.url));
1386 get_runner.AddRead(kShoutcastResponse);
1387 get_runner.SetupParserAndSendRequest();
1388
1389 get_runner.ReadHeadersExpectingError(
1390 test_case.expected_shoutcast_header_error);
1391 if (test_case.expected_shoutcast_header_error != OK)
1392 continue;
1393
1394 ASSERT_TRUE(get_runner.response_info()->headers);
1395 EXPECT_EQ("HTTP/0.9 200 OK",
1396 get_runner.response_info()->headers->GetStatusLine());
1397
1398 EXPECT_EQ(0, get_runner.parser()->received_bytes());
1399 int read_lengths[] = {static_cast<int>(kShoutcastResponse.size()), 0};
1400 get_runner.ReadBody(kShoutcastResponse.size(), read_lengths);
1401 EXPECT_EQ(kShoutcastResponse.size(),
1402 static_cast<size_t>(get_runner.parser()->received_bytes()));
1403 EXPECT_EQ(HttpConnectionInfo::kHTTP0_9,
1404 get_runner.response_info()->connection_info);
1405 }
1406 }
1407
TEST(HttpStreamParser,ContinueWithBody)1408 TEST(HttpStreamParser, ContinueWithBody) {
1409 const std::string kResponse =
1410 "HTTP/1.1 100 Continue\r\n\r\nhello\r\nworld\r\n";
1411
1412 SimpleGetRunner get_runner;
1413 get_runner.set_url(GURL("http://foo.com/"));
1414 get_runner.AddRead(kResponse);
1415 get_runner.SetupParserAndSendRequest();
1416
1417 get_runner.ReadHeadersExpectingError(OK);
1418 ASSERT_TRUE(get_runner.response_info()->headers);
1419 EXPECT_EQ("HTTP/1.1 100 Continue",
1420 get_runner.response_info()->headers->GetStatusLine());
1421
1422 // We ignore informational responses and start reading the next response in
1423 // the stream. This simulates the behavior.
1424 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1425 }
1426
TEST(HttpStreamParser,NullFails)1427 TEST(HttpStreamParser, NullFails) {
1428 const char kTestHeaders[] =
1429 "HTTP/1.1 200 OK\r\n"
1430 "Foo: Bar\r\n"
1431 "Content-Length: 4\r\n\r\n";
1432
1433 // Try inserting a null at each position in kTestHeaders. Every location
1434 // should result in an error.
1435 //
1436 // Need to start at 4 because HttpStreamParser will treat the response as
1437 // HTTP/0.9 if it doesn't see "HTTP", and need to end at -1 because "\r\n\r"
1438 // is currently treated as a valid end of header marker.
1439 for (size_t i = 4; i < std::size(kTestHeaders) - 1; ++i) {
1440 std::string read_data(kTestHeaders);
1441 read_data.insert(i, 1, '\0');
1442 read_data.append("body");
1443 SimpleGetRunner get_runner;
1444 get_runner.set_url(GURL("http://foo.test/"));
1445 get_runner.AddRead(read_data);
1446 get_runner.SetupParserAndSendRequest();
1447
1448 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1449 }
1450 }
1451
1452 // Make sure that Shoutcast is recognized when receiving one byte at a time.
TEST(HttpStreamParser,ShoutcastSingleByteReads)1453 TEST(HttpStreamParser, ShoutcastSingleByteReads) {
1454 SimpleGetRunner get_runner;
1455 get_runner.set_url(GURL("http://foo.com:8080/"));
1456 get_runner.AddRead("i");
1457 get_runner.AddRead("c");
1458 get_runner.AddRead("Y");
1459 // Needed because HttpStreamParser::Read returns ERR_CONNECTION_CLOSED on
1460 // small response headers, which HttpNetworkTransaction replaces with net::OK.
1461 // TODO(mmenke): Can we just change that behavior?
1462 get_runner.AddRead(" Extra stuff");
1463 get_runner.SetupParserAndSendRequest();
1464
1465 get_runner.ReadHeadersExpectingError(OK);
1466 EXPECT_EQ("HTTP/0.9 200 OK",
1467 get_runner.response_info()->headers->GetStatusLine());
1468 }
1469
1470 // Make sure that Shoutcast is recognized when receiving any string starting
1471 // with "ICY", regardless of capitalization, and without a space following it
1472 // (The latter behavior is just to match HTTP detection).
TEST(HttpStreamParser,ShoutcastWeirdHeader)1473 TEST(HttpStreamParser, ShoutcastWeirdHeader) {
1474 SimpleGetRunner get_runner;
1475 get_runner.set_url(GURL("http://foo.com:8080/"));
1476 get_runner.AddRead("iCyCreamSundae");
1477 get_runner.SetupParserAndSendRequest();
1478
1479 get_runner.ReadHeadersExpectingError(OK);
1480 EXPECT_EQ("HTTP/0.9 200 OK",
1481 get_runner.response_info()->headers->GetStatusLine());
1482 }
1483
1484 // Make sure that HTTP/0.9 isn't allowed in the truncated header case on a weird
1485 // port.
TEST(HttpStreamParser,Http09TruncatedHeaderPortTest)1486 TEST(HttpStreamParser, Http09TruncatedHeaderPortTest) {
1487 SimpleGetRunner get_runner;
1488 get_runner.set_url(GURL("http://foo.com:8080/"));
1489 std::string response = "HT";
1490 get_runner.AddRead(response);
1491 get_runner.SetupParserAndSendRequest();
1492
1493 get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
1494 }
1495
1496 // Test basic case where there is no keep-alive or extra data from the socket,
1497 // and the entire response is received in a single read.
TEST(HttpStreamParser,ReceivedBytesNormal)1498 TEST(HttpStreamParser, ReceivedBytesNormal) {
1499 std::string headers =
1500 "HTTP/1.0 200 OK\r\n"
1501 "Content-Length: 7\r\n\r\n";
1502 std::string body = "content";
1503 std::string response = headers + body;
1504
1505 SimpleGetRunner get_runner;
1506 get_runner.AddRead(response);
1507 get_runner.SetupParserAndSendRequest();
1508 get_runner.ReadHeaders();
1509 int64_t headers_size = headers.size();
1510 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1511 int body_size = body.size();
1512 int read_lengths[] = {body_size, 0};
1513 get_runner.ReadBody(body_size, read_lengths);
1514 int64_t response_size = response.size();
1515 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1516 EXPECT_EQ(HttpConnectionInfo::kHTTP1_0,
1517 get_runner.response_info()->connection_info);
1518 }
1519
1520 // Test that bytes that represent "next" response are not counted
1521 // as current response "received_bytes".
TEST(HttpStreamParser,ReceivedBytesExcludesNextResponse)1522 TEST(HttpStreamParser, ReceivedBytesExcludesNextResponse) {
1523 std::string headers = "HTTP/1.1 200 OK\r\n"
1524 "Content-Length: 8\r\n\r\n";
1525 std::string body = "content8";
1526 std::string response = headers + body;
1527 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1528 std::string data = response + next_response;
1529
1530 SimpleGetRunner get_runner;
1531 get_runner.AddRead(data);
1532 get_runner.SetupParserAndSendRequest();
1533 get_runner.ReadHeaders();
1534 EXPECT_EQ(39, get_runner.parser()->received_bytes());
1535 int64_t headers_size = headers.size();
1536 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1537 int body_size = body.size();
1538 int read_lengths[] = {body_size, 0};
1539 get_runner.ReadBody(body_size, read_lengths);
1540 int64_t response_size = response.size();
1541 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1542 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1543 EXPECT_EQ(HttpConnectionInfo::kHTTP1_1,
1544 get_runner.response_info()->connection_info);
1545 }
1546
1547 // Test that "received_bytes" calculation works fine when last read
1548 // contains more data than requested by user.
1549 // We send data in two reads:
1550 // 1) Headers + beginning of response
1551 // 2) remaining part of response + next response start
1552 // We setup user read buffer so it fully accepts the beginning of response
1553 // body, but it is larger than remaining part of body.
TEST(HttpStreamParser,ReceivedBytesMultiReadExcludesNextResponse)1554 TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesNextResponse) {
1555 std::string headers = "HTTP/1.1 200 OK\r\n"
1556 "Content-Length: 36\r\n\r\n";
1557 int64_t user_buf_len = 32;
1558 std::string body_start = std::string(user_buf_len, '#');
1559 int body_start_size = body_start.size();
1560 EXPECT_EQ(user_buf_len, body_start_size);
1561 std::string response_start = headers + body_start;
1562 std::string body_end = "abcd";
1563 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1564 std::string response_end = body_end + next_response;
1565
1566 SimpleGetRunner get_runner;
1567 get_runner.AddRead(response_start);
1568 get_runner.AddRead(response_end);
1569 get_runner.SetupParserAndSendRequest();
1570 get_runner.ReadHeaders();
1571 int64_t headers_size = headers.size();
1572 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1573 int body_end_size = body_end.size();
1574 int read_lengths[] = {body_start_size, body_end_size, 0};
1575 get_runner.ReadBody(body_start_size, read_lengths);
1576 int64_t response_size = response_start.size() + body_end_size;
1577 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1578 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1579 EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1580 }
1581
TEST(HttpStreamParser,ReceivedBytesMultiReadExcludesExtraData)1582 TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesExtraData) {
1583 const std::string headers =
1584 "HTTP/1.1 200 OK\r\n"
1585 "Content-Length: 36\r\n\r\n";
1586 const int64_t user_buf_len = 32;
1587 const std::string body_start = std::string(user_buf_len, '#');
1588 const int body_start_size = body_start.size();
1589 EXPECT_EQ(user_buf_len, body_start_size);
1590 const std::string body_end = "abcd";
1591 const int body_end_size = body_end.size();
1592 const std::string body = body_start + body_end;
1593 const int body_size = body.size();
1594 const std::string extra_data = "HTTP/1.1 200 OK\r\n\r\nFOO";
1595 const std::string read_data = body + extra_data;
1596
1597 SimpleGetRunner get_runner;
1598 get_runner.AddRead(headers);
1599 get_runner.AddRead(read_data);
1600 get_runner.SetupParserAndSendRequest();
1601 get_runner.ReadHeaders();
1602 const int headers_size = headers.size();
1603 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1604 int read_lengths[] = {body_start_size, body_end_size, 0};
1605 get_runner.ReadBody(body_start_size, read_lengths);
1606 const int response_size = headers_size + body_size;
1607 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1608 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1609 EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1610 }
1611
TEST(HttpStreamParser,ReceivedBytesAsyncMultiReadExcludesExtraData)1612 TEST(HttpStreamParser, ReceivedBytesAsyncMultiReadExcludesExtraData) {
1613 base::test::SingleThreadTaskEnvironment task_environment;
1614
1615 const std::string headers =
1616 "HTTP/1.1 200 OK\r\n"
1617 "Content-Length: 36\r\n\r\n";
1618 const int64_t user_buf_len = 32;
1619 const std::string body_start = std::string(user_buf_len, '#');
1620 const int body_start_size = body_start.size();
1621 EXPECT_EQ(user_buf_len, body_start_size);
1622 const std::string body_end = "abcd";
1623 const int body_end_size = body_end.size();
1624 const std::string body = body_start + body_end;
1625 const int body_size = body.size();
1626 const std::string extra_data = "HTTP/1.1 200 OK\r\n\r\nFOO";
1627 const std::string read_data = body_end + extra_data;
1628
1629 SimpleGetRunner get_runner;
1630 get_runner.AddRead(headers);
1631 get_runner.AddRead(body_start);
1632 get_runner.AddAsyncRead(read_data);
1633 get_runner.SetupParserAndSendRequest();
1634 get_runner.ReadHeaders();
1635 const int headers_size = headers.size();
1636 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1637 int read_lengths[] = {body_start_size, -1, body_end_size, 0};
1638 get_runner.ReadBody(body_start_size, read_lengths);
1639 const int response_size = headers_size + body_size;
1640 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1641 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1642 EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1643 }
1644
TEST(HttpStreamParser,ReceivedBytesExcludesExtraDataLargeBuffer)1645 TEST(HttpStreamParser, ReceivedBytesExcludesExtraDataLargeBuffer) {
1646 const std::string headers =
1647 "HTTP/1.1 200 OK\r\n"
1648 "Content-Length: 36\r\n\r\n";
1649 const std::string body = std::string(36, '#');
1650 const int body_size = body.size();
1651 const std::string extra_data = std::string(14, '!');
1652 const std::string response = headers + body + extra_data;
1653 const int response_size = response.size();
1654
1655 SimpleGetRunner get_runner;
1656 get_runner.AddRead(response);
1657 get_runner.SetupParserAndSendRequest();
1658 get_runner.ReadHeaders();
1659 const int headers_size = headers.size();
1660 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1661 int read_lengths[] = {body_size, 0};
1662 get_runner.ReadBody(response_size, read_lengths);
1663 const int actual_response_size = headers_size + body_size;
1664 EXPECT_EQ(actual_response_size, get_runner.parser()->received_bytes());
1665 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1666 EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1667 }
1668
TEST(HttpStreamParser,ReceivedBytesExcludesExtraDataSmallBuffer)1669 TEST(HttpStreamParser, ReceivedBytesExcludesExtraDataSmallBuffer) {
1670 const std::string headers =
1671 "HTTP/1.1 200 OK\r\n"
1672 "Content-Length: 36\r\n\r\n";
1673 const std::string body = std::string(36, '#');
1674 const int body_size = body.size();
1675 const std::string extra_data = std::string(14, '!');
1676 const std::string response = headers + body + extra_data;
1677
1678 SimpleGetRunner get_runner;
1679 get_runner.AddRead(response);
1680 get_runner.SetupParserAndSendRequest();
1681 get_runner.ReadHeaders();
1682 const int headers_size = headers.size();
1683 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1684 int read_lengths[] = {10, 10, 10, 6, 0};
1685 get_runner.ReadBody(10, read_lengths);
1686 const int actual_response_size = headers_size + body_size;
1687 EXPECT_EQ(actual_response_size, get_runner.parser()->received_bytes());
1688 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1689 EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1690 }
1691
1692 // Test that "received_bytes" calculation works fine when there is no
1693 // network activity at all; that is when all data is read from read buffer.
1694 // In this case read buffer contains two responses. We expect that only
1695 // bytes that correspond to the first one are taken into account.
TEST(HttpStreamParser,ReceivedBytesFromReadBufExcludesNextResponse)1696 TEST(HttpStreamParser, ReceivedBytesFromReadBufExcludesNextResponse) {
1697 std::string headers = "HTTP/1.1 200 OK\r\n"
1698 "Content-Length: 7\r\n\r\n";
1699 std::string body = "content";
1700 std::string response = headers + body;
1701 std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
1702 std::string data = response + next_response;
1703
1704 SimpleGetRunner get_runner;
1705 get_runner.AddInitialData(data);
1706 get_runner.SetupParserAndSendRequest();
1707 get_runner.ReadHeaders();
1708 int64_t headers_size = headers.size();
1709 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1710 int body_size = body.size();
1711 int read_lengths[] = {body_size, 0};
1712 get_runner.ReadBody(body_size, read_lengths);
1713 int64_t response_size = response.size();
1714 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1715 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1716 EXPECT_FALSE(get_runner.parser()->CanReuseConnection());
1717 }
1718
1719 // Test calculating "received_bytes" when part of request has been already
1720 // loaded and placed to read buffer by previous stream parser.
TEST(HttpStreamParser,ReceivedBytesUseReadBuf)1721 TEST(HttpStreamParser, ReceivedBytesUseReadBuf) {
1722 std::string buffer = "HTTP/1.1 200 OK\r\n";
1723 std::string remaining_headers = "Content-Length: 7\r\n\r\n";
1724 int64_t headers_size = buffer.size() + remaining_headers.size();
1725 std::string body = "content";
1726 std::string response = remaining_headers + body;
1727
1728 SimpleGetRunner get_runner;
1729 get_runner.AddInitialData(buffer);
1730 get_runner.AddRead(response);
1731 get_runner.SetupParserAndSendRequest();
1732 get_runner.ReadHeaders();
1733 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1734 int body_size = body.size();
1735 int read_lengths[] = {body_size, 0};
1736 get_runner.ReadBody(body_size, read_lengths);
1737 EXPECT_EQ(headers_size + body_size, get_runner.parser()->received_bytes());
1738 EXPECT_EQ(0, get_runner.read_buffer()->offset());
1739 }
1740
1741 // Test the case when the resulting read_buf contains both unused bytes and
1742 // bytes ejected by chunked-encoding filter.
TEST(HttpStreamParser,ReceivedBytesChunkedTransferExcludesNextResponse)1743 TEST(HttpStreamParser, ReceivedBytesChunkedTransferExcludesNextResponse) {
1744 std::string response = "HTTP/1.1 200 OK\r\n"
1745 "Transfer-Encoding: chunked\r\n\r\n"
1746 "7\r\nChunk 1\r\n"
1747 "8\r\nChunky 2\r\n"
1748 "6\r\nTest 3\r\n"
1749 "0\r\n\r\n";
1750 std::string next_response = "foo bar\r\n";
1751 std::string data = response + next_response;
1752
1753 SimpleGetRunner get_runner;
1754 get_runner.AddInitialData(data);
1755 get_runner.SetupParserAndSendRequest();
1756 get_runner.ReadHeaders();
1757 int read_lengths[] = {4, 3, 6, 2, 6, 0};
1758 get_runner.ReadBody(7, read_lengths);
1759 int64_t response_size = response.size();
1760 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1761 int64_t next_response_size = next_response.size();
1762 EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
1763 }
1764
1765 // Test that data transfered in multiple reads is correctly processed.
1766 // We feed data into 4-bytes reads. Also we set length of read
1767 // buffer to 5-bytes to test all possible buffer misaligments.
TEST(HttpStreamParser,ReceivedBytesMultipleReads)1768 TEST(HttpStreamParser, ReceivedBytesMultipleReads) {
1769 std::string headers = "HTTP/1.1 200 OK\r\n"
1770 "Content-Length: 33\r\n\r\n";
1771 std::string body = "foo bar baz\r\n"
1772 "sputnik mir babushka";
1773 std::string response = headers + body;
1774
1775 size_t receive_length = 4;
1776 std::vector<std::string> blocks;
1777 for (size_t i = 0; i < response.size(); i += receive_length) {
1778 size_t length = std::min(receive_length, response.size() - i);
1779 blocks.push_back(response.substr(i, length));
1780 }
1781
1782 SimpleGetRunner get_runner;
1783 for (const auto& block : blocks)
1784 get_runner.AddRead(block);
1785 get_runner.SetupParserAndSendRequest();
1786 get_runner.ReadHeaders();
1787 int64_t headers_size = headers.size();
1788 EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
1789 int read_lengths[] = {1, 4, 4, 4, 4, 4, 4, 4, 4, 0};
1790 get_runner.ReadBody(receive_length + 1, read_lengths);
1791 int64_t response_size = response.size();
1792 EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
1793 }
1794
1795 // Test timing information of responses that don't have informational (1xx)
1796 // response headers.
TEST(HttpStreamParser,NonInformationalResponseStart)1797 TEST(HttpStreamParser, NonInformationalResponseStart) {
1798 base::test::TaskEnvironment task_environment(
1799 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1800
1801 std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1802 std::string response_headers2 = "Content-Length: 7\r\n\r\n";
1803 int64_t response_headers_size =
1804 response_headers1.size() + response_headers2.size();
1805
1806 std::string response_body = "content";
1807 int64_t response_size = response_headers_size + response_body.size();
1808
1809 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1810
1811 MockRead reads[] = {
1812 // Add pauses between header fragments so that the test runner can advance
1813 // the mock clock to test timing information.
1814 MockRead(ASYNC, 1, response_headers1.c_str()),
1815 MockRead(ASYNC, ERR_IO_PENDING, 2),
1816 MockRead(ASYNC, 3, response_headers2.c_str()),
1817 MockRead(ASYNC, 4, response_body.c_str()),
1818 };
1819
1820 // Set up the sequenced socket data.
1821 SequencedSocketData sequenced_socket_data(reads, writes);
1822 std::unique_ptr<StreamSocket> stream_socket =
1823 CreateConnectedSocket(&sequenced_socket_data);
1824
1825 // Set up the http stream parser.
1826 HttpRequestInfo request;
1827 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1828 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1829 &request, read_buffer.get(), NetLogWithSource());
1830
1831 // Send a request.
1832 HttpResponseInfo response;
1833 TestCompletionCallback callback;
1834 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1835 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1836 callback.callback()),
1837 IsOk());
1838
1839 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1840 IsError(ERR_IO_PENDING));
1841 task_environment.AdvanceClock(base::Seconds(1));
1842
1843 // [seq=1 --> seq=2] The parser reads the first fragment of the response
1844 // headers and then pauses to advance the mock clock.
1845 base::TimeTicks first_response_start_time = task_environment.NowTicks();
1846 sequenced_socket_data.RunUntilPaused();
1847 task_environment.AdvanceClock(base::Seconds(1));
1848
1849 // [seq=3] The parser reads the second fragment of the response headers.
1850 sequenced_socket_data.Resume();
1851 EXPECT_THAT(callback.WaitForResult(), IsOk());
1852
1853 // Check the received headers.
1854 EXPECT_EQ(200, response.headers->response_code());
1855 EXPECT_EQ(response_headers_size, parser.received_bytes());
1856
1857 // No informational responses were served. The first response start time
1858 // should be equal to the non-informational response start time.
1859 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
1860 EXPECT_EQ(parser.non_informational_response_start_time(),
1861 first_response_start_time);
1862
1863 // [seq=4] The parser reads the response body.
1864 auto body_buffer =
1865 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
1866 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
1867 callback.callback());
1868 EXPECT_THAT(callback.GetResult(result), response_body.size());
1869
1870 // Check the received body.
1871 EXPECT_EQ(response_size, parser.received_bytes());
1872 }
1873
1874 // Test timing information of responses that don't have informational (1xx)
1875 // response headers, and have no response body.
TEST(HttpStreamParser,NonInformationalResponseStartWithoutBody)1876 TEST(HttpStreamParser, NonInformationalResponseStartWithoutBody) {
1877 base::test::TaskEnvironment task_environment(
1878 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1879
1880 std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1881 std::string response_headers2 = "Content-Length: 0\r\n\r\n";
1882 int64_t response_size = response_headers1.size() + response_headers2.size();
1883
1884 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1885
1886 MockRead reads[] = {
1887 // Add pauses between header fragments so that the test runner can advance
1888 // the mock clock to test timing information.
1889 MockRead(ASYNC, 1, response_headers1.c_str()),
1890 MockRead(ASYNC, ERR_IO_PENDING, 2),
1891 MockRead(ASYNC, 3, response_headers2.c_str()),
1892 };
1893
1894 // Set up the sequenced socket data.
1895 SequencedSocketData sequenced_socket_data(reads, writes);
1896 std::unique_ptr<StreamSocket> stream_socket =
1897 CreateConnectedSocket(&sequenced_socket_data);
1898
1899 // Set up the http stream parser.
1900 HttpRequestInfo request;
1901 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1902 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1903 &request, read_buffer.get(), NetLogWithSource());
1904
1905 // Send a request.
1906 HttpResponseInfo response;
1907 TestCompletionCallback callback;
1908 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1909 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1910 callback.callback()),
1911 IsOk());
1912
1913 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
1914 IsError(ERR_IO_PENDING));
1915 task_environment.AdvanceClock(base::Seconds(1));
1916
1917 // [seq=1 --> seq=2] The parser reads the first fragment of the response
1918 // headers and then pauses to advance the mock clock.
1919 base::TimeTicks first_response_start_time = task_environment.NowTicks();
1920 sequenced_socket_data.RunUntilPaused();
1921 task_environment.AdvanceClock(base::Seconds(1));
1922
1923 // [seq=3] The parser reads the second fragment of the response headers.
1924 sequenced_socket_data.Resume();
1925 EXPECT_THAT(callback.WaitForResult(), IsOk());
1926
1927 // Check the received headers.
1928 EXPECT_EQ(200, response.headers->response_code());
1929 EXPECT_EQ(response_size, parser.received_bytes());
1930
1931 // No informational responses were served. The first response start time
1932 // should be equal to the non-informational response start time.
1933 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
1934 EXPECT_EQ(parser.non_informational_response_start_time(),
1935 first_response_start_time);
1936
1937 // [seq=4] The parser reads the response body.
1938 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(10);
1939 int result = parser.ReadResponseBody(body_buffer.get(), body_buffer->size(),
1940 callback.callback());
1941 EXPECT_THAT(callback.GetResult(result), IsError(OK));
1942 }
1943
1944 // Test that "continue" HTTP header is counted as "received_bytes".
TEST(HttpStreamParser,ReceivedBytesIncludesContinueHeader)1945 TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) {
1946 base::test::TaskEnvironment task_environment(
1947 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
1948
1949 std::string status100_response_headers1 = "HTTP/1.1 100 ";
1950 std::string status100_response_headers2 = "Continue\r\n\r\n";
1951 int64_t status100_response_headers_size =
1952 status100_response_headers1.size() + status100_response_headers2.size();
1953
1954 std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
1955 std::string response_headers2 = "Content-Length: 7\r\n\r\n";
1956 int64_t response_headers_size =
1957 response_headers1.size() + response_headers2.size();
1958
1959 std::string response_body = "content";
1960 int64_t response_size = status100_response_headers_size +
1961 response_headers_size + response_body.size();
1962
1963 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
1964
1965 MockRead reads[] = {
1966 // Add pauses between header fragments so that the test runner can advance
1967 // the mock clock to test timing information.
1968
1969 // 100 response headers.
1970 MockRead(ASYNC, 1, status100_response_headers1.c_str()),
1971 MockRead(ASYNC, ERR_IO_PENDING, 2),
1972 MockRead(ASYNC, 3, status100_response_headers2.c_str()),
1973 MockRead(ASYNC, ERR_IO_PENDING, 4),
1974
1975 // 200 response headers and body.
1976 MockRead(ASYNC, 5, response_headers1.c_str()),
1977 MockRead(ASYNC, ERR_IO_PENDING, 6),
1978 MockRead(ASYNC, 7, response_headers2.c_str()),
1979 MockRead(ASYNC, 8, response_body.c_str()),
1980 };
1981
1982 // Set up the sequenced socket data.
1983 SequencedSocketData sequenced_socket_data(reads, writes);
1984 std::unique_ptr<StreamSocket> stream_socket =
1985 CreateConnectedSocket(&sequenced_socket_data);
1986
1987 // Set up the http stream parser.
1988 HttpRequestInfo request;
1989 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
1990 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
1991 &request, read_buffer.get(), NetLogWithSource());
1992
1993 // Send a request.
1994 HttpResponseInfo response;
1995 TestCompletionCallback callback;
1996 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
1997 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
1998 callback.callback()),
1999 IsOk());
2000
2001 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2002 IsError(ERR_IO_PENDING));
2003
2004 // [seq=1 --> seq=2] The parser reads the first fragment of the informational
2005 // response headers and then pauses to advance the mock clock.
2006 base::TimeTicks first_response_start_time = task_environment.NowTicks();
2007 sequenced_socket_data.RunUntilPaused();
2008 task_environment.AdvanceClock(base::Seconds(1));
2009
2010 // [seq=3] The parser reads the second fragment of the informational response
2011 // headers.
2012 sequenced_socket_data.Resume();
2013 EXPECT_THAT(callback.WaitForResult(), IsOk());
2014
2015 // Check the received headers.
2016 EXPECT_EQ(100, response.headers->response_code());
2017 EXPECT_EQ(status100_response_headers_size, parser.received_bytes());
2018
2019 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2020 IsError(ERR_IO_PENDING));
2021
2022 // [seq=4] The parser pauses to advance the clock.
2023 sequenced_socket_data.RunUntilPaused();
2024 task_environment.AdvanceClock(base::Seconds(1));
2025
2026 // [seq=5 --> seq=6] The parser reads the first fragment of the
2027 // non-informational response headers and then pauses to advance the mock
2028 // clock.
2029 base::TimeTicks non_informational_response_start_time =
2030 task_environment.NowTicks();
2031 sequenced_socket_data.Resume();
2032 sequenced_socket_data.RunUntilPaused();
2033 task_environment.AdvanceClock(base::Seconds(1));
2034
2035 // [seq=7] The parser reads the second fragment of the non-informational
2036 // response headers.
2037 sequenced_socket_data.Resume();
2038 EXPECT_THAT(callback.WaitForResult(), IsOk());
2039 task_environment.AdvanceClock(base::Seconds(1));
2040
2041 // Check the received headers.
2042 EXPECT_EQ(200, response.headers->response_code());
2043 EXPECT_EQ(status100_response_headers_size + response_headers_size,
2044 parser.received_bytes());
2045
2046 // The first response start time should be captured at the time the first
2047 // fragment of the informational response headers is received.
2048 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2049 // The non-informational response start time should be captured at the time
2050 // the first fragment of the non-informational response headers is received.
2051 EXPECT_EQ(parser.non_informational_response_start_time(),
2052 non_informational_response_start_time);
2053 // The first response start time should be earlier than the non-informational
2054 // response start time.
2055 EXPECT_LT(parser.first_response_start_time(),
2056 parser.non_informational_response_start_time());
2057
2058 // [seq=8] The parser reads the non-informational response body.
2059 auto body_buffer =
2060 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2061 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2062 callback.callback());
2063 EXPECT_THAT(callback.GetResult(result), response_body.size());
2064
2065 // Check the received body.
2066 EXPECT_EQ(response_size, parser.received_bytes());
2067 }
2068
2069 // Test that "early hints" HTTP header is counted as "received_bytes".
2070 // 103 Early Hints hasn't been implemented yet and should be ignored, but we
2071 // collect timing information for the experiment (https://crbug.com/1093693).
TEST(HttpStreamParser,EarlyHints)2072 TEST(HttpStreamParser, EarlyHints) {
2073 base::test::TaskEnvironment task_environment(
2074 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
2075
2076 std::string status103_response_headers1 = "HTTP/1.1 103 Early Hints\r\n";
2077 std::string status103_response_headers2 =
2078 "Link: </style.css>; rel=preload; as=style\r\n";
2079 std::string status103_response_headers3 =
2080 "Link: </script.js>; rel=preload; as=script\r\n\r\n";
2081 int64_t status103_response_headers_size = status103_response_headers1.size() +
2082 status103_response_headers2.size() +
2083 status103_response_headers3.size();
2084
2085 std::string response_headers1 = "HTTP/1.1 200 OK\r\n";
2086 std::string response_headers2 = "Content-Length: 7\r\n\r\n";
2087 int64_t response_headers_size =
2088 response_headers1.size() + response_headers2.size();
2089
2090 std::string response_body = "content";
2091 int64_t response_size = status103_response_headers_size +
2092 response_headers_size + response_body.size();
2093
2094 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
2095
2096 MockRead reads[] = {
2097 // Add pauses between header fragments so that the test runner can advance
2098 // the mock clock to test timing information.
2099
2100 // 103 Early Hints response headers.
2101 MockRead(ASYNC, 1, status103_response_headers1.c_str()),
2102 MockRead(ASYNC, ERR_IO_PENDING, 2),
2103 MockRead(ASYNC, 3, status103_response_headers2.c_str()),
2104 MockRead(ASYNC, ERR_IO_PENDING, 4),
2105 MockRead(ASYNC, 5, status103_response_headers3.c_str()),
2106 MockRead(ASYNC, ERR_IO_PENDING, 6),
2107
2108 // 200 response headers and body.
2109 MockRead(ASYNC, 7, response_headers1.c_str()),
2110 MockRead(ASYNC, ERR_IO_PENDING, 8),
2111 MockRead(ASYNC, 9, response_headers2.c_str()),
2112 MockRead(ASYNC, 10, response_body.c_str()),
2113 };
2114
2115 // Set up the sequenced socket data.
2116 SequencedSocketData sequenced_socket_data(reads, writes);
2117 std::unique_ptr<StreamSocket> stream_socket =
2118 CreateConnectedSocket(&sequenced_socket_data);
2119
2120 // Set up the http stream parser.
2121 HttpRequestInfo request;
2122 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
2123 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
2124 &request, read_buffer.get(), NetLogWithSource());
2125
2126 // Send a request.
2127 HttpResponseInfo response;
2128 TestCompletionCallback callback;
2129 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
2130 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
2131 callback.callback()),
2132 IsOk());
2133
2134 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2135 IsError(ERR_IO_PENDING));
2136
2137 // [seq=1 --> seq=2] The parser reads the first fragment of the informational
2138 // response headers and then pauses to advance the mock clock.
2139 base::TimeTicks first_response_start_time = task_environment.NowTicks();
2140 sequenced_socket_data.RunUntilPaused();
2141 task_environment.AdvanceClock(base::Seconds(1));
2142
2143 // [seq=3 --> seq=4] The parser reads the second fragment of the informational
2144 // response headers and then pauses to advance the mock clock.
2145 sequenced_socket_data.Resume();
2146 sequenced_socket_data.RunUntilPaused();
2147 task_environment.AdvanceClock(base::Seconds(1));
2148
2149 // [seq=5] The parser reads the third fragment of the informational response
2150 // headers.
2151 sequenced_socket_data.Resume();
2152 EXPECT_THAT(callback.WaitForResult(), IsOk());
2153
2154 // Check the received headers.
2155 EXPECT_EQ(103, response.headers->response_code());
2156 EXPECT_EQ(status103_response_headers_size, parser.received_bytes());
2157
2158 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2159 IsError(ERR_IO_PENDING));
2160
2161 // [seq=6] The parser pauses to advance the clock.
2162 sequenced_socket_data.RunUntilPaused();
2163 task_environment.AdvanceClock(base::Seconds(1));
2164
2165 // [seq=7 --> seq=8] The parser reads the first fragment of the
2166 // non-informational response headers and then pauses to advance the mock
2167 // clock.
2168 base::TimeTicks non_informational_response_start_time =
2169 task_environment.NowTicks();
2170 sequenced_socket_data.Resume();
2171 sequenced_socket_data.RunUntilPaused();
2172 task_environment.AdvanceClock(base::Seconds(1));
2173
2174 // [seq=9] The parser reads the second fragment of the non-informational
2175 // response headers.
2176 sequenced_socket_data.Resume();
2177 EXPECT_THAT(callback.WaitForResult(), IsOk());
2178 task_environment.AdvanceClock(base::Seconds(1));
2179
2180 // Check the received headers.
2181 EXPECT_EQ(200, response.headers->response_code());
2182 EXPECT_EQ(status103_response_headers_size + response_headers_size,
2183 parser.received_bytes());
2184
2185 // The first response start time and first early hints time should be captured
2186 // at the time the first fragment of the informational response headers is
2187 // received.
2188 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2189 EXPECT_EQ(parser.first_early_hints_time(), first_response_start_time);
2190 // The non-informational response start time should be captured at the time
2191 // the first fragment of the non-informational response headers is received.
2192 EXPECT_EQ(parser.non_informational_response_start_time(),
2193 non_informational_response_start_time);
2194 // The first response start time should be earlier than the non-informational
2195 // response start time.
2196 EXPECT_LT(parser.first_response_start_time(),
2197 parser.non_informational_response_start_time());
2198
2199 // [seq=10] The parser reads the non-informational response body.
2200 auto body_buffer =
2201 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2202 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2203 callback.callback());
2204 EXPECT_THAT(callback.GetResult(result), response_body.size());
2205
2206 // Check the received body.
2207 EXPECT_EQ(response_size, parser.received_bytes());
2208 }
2209
2210 // Test the case where informational response headers and non-informational
2211 // response headers are packed in the same fragment.
TEST(HttpStreamParser,MixedResponseHeaders)2212 TEST(HttpStreamParser, MixedResponseHeaders) {
2213 base::test::TaskEnvironment task_environment(
2214 base::test::TaskEnvironment::TimeSource::MOCK_TIME);
2215
2216 std::string status100_response_headers = "HTTP/1.1 100 ";
2217 std::string mixed_response_headers = "Continue\r\n\r\nHTTP/1.1 200 OK\r\n";
2218 std::string response_headers = "Content-Length: 7\r\n\r\n";
2219 int64_t status100_response_headers_size =
2220 status100_response_headers.size() + 12;
2221 int64_t response_headers_size = response_headers.size() + 17;
2222
2223 std::string response_body = "content";
2224 int64_t response_size = status100_response_headers_size +
2225 response_headers_size + response_body.size();
2226
2227 MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n")};
2228
2229 MockRead reads[] = {
2230 // Add pauses between header fragments so that the test runner can advance
2231 // the mock clock to test timing information.
2232
2233 // 100 response headers.
2234 MockRead(ASYNC, 1, status100_response_headers.c_str()),
2235 MockRead(ASYNC, ERR_IO_PENDING, 2),
2236
2237 // Mixed response headers.
2238 MockRead(ASYNC, 3, mixed_response_headers.c_str()),
2239 MockRead(ASYNC, ERR_IO_PENDING, 4),
2240
2241 // 200 response headers and body.
2242 MockRead(ASYNC, 5, response_headers.c_str()),
2243 MockRead(ASYNC, 6, response_body.c_str()),
2244 };
2245
2246 // Set up the sequenced socket data.
2247 SequencedSocketData sequenced_socket_data(reads, writes);
2248 std::unique_ptr<StreamSocket> stream_socket =
2249 CreateConnectedSocket(&sequenced_socket_data);
2250
2251 // Set up the http stream parser.
2252 HttpRequestInfo request;
2253 auto read_buffer = base::MakeRefCounted<GrowableIOBuffer>();
2254 HttpStreamParser parser(stream_socket.get(), /*connection_is_reused=*/false,
2255 &request, read_buffer.get(), NetLogWithSource());
2256
2257 // Send a request.
2258 HttpResponseInfo response;
2259 TestCompletionCallback callback;
2260 EXPECT_THAT(parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(),
2261 TRAFFIC_ANNOTATION_FOR_TESTS, &response,
2262 callback.callback()),
2263 IsOk());
2264
2265 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2266 IsError(ERR_IO_PENDING));
2267
2268 // [seq=1 --> seq=2] The parser reads the first fragment of the informational
2269 // response headers and then pauses to advance the mock clock.
2270 base::TimeTicks first_response_start_time = task_environment.NowTicks();
2271 sequenced_socket_data.RunUntilPaused();
2272 task_environment.AdvanceClock(base::Seconds(1));
2273
2274 // [seq=3] The parser reads the second fragment of the informational response
2275 // headers.
2276 sequenced_socket_data.Resume();
2277 EXPECT_THAT(callback.WaitForResult(), IsOk());
2278
2279 // Check the received headers.
2280 EXPECT_EQ(100, response.headers->response_code());
2281 EXPECT_EQ(status100_response_headers_size, parser.received_bytes());
2282
2283 EXPECT_THAT(parser.ReadResponseHeaders(callback.callback()),
2284 IsError(ERR_IO_PENDING));
2285
2286 // [seq=3 --> seq=4] The parser reads the first fragment of the
2287 // non-informational response headers and then pauses to advance the mock
2288 // clock.
2289 base::TimeTicks non_informational_response_start_time =
2290 task_environment.NowTicks();
2291 sequenced_socket_data.RunUntilPaused();
2292 task_environment.AdvanceClock(base::Seconds(1));
2293
2294 // [seq=5] The parser reads the second fragment of the non-informational
2295 // response headers.
2296 sequenced_socket_data.Resume();
2297 EXPECT_THAT(callback.WaitForResult(), IsOk());
2298
2299 // Check the received headers.
2300 EXPECT_EQ(200, response.headers->response_code());
2301 EXPECT_EQ(status100_response_headers_size + response_headers_size,
2302 parser.received_bytes());
2303
2304 // The first response start time should be captured at the time the first
2305 // fragment of the informational response headers is received.
2306 EXPECT_EQ(parser.first_response_start_time(), first_response_start_time);
2307 // The non-informational response start time should be captured at the time
2308 // the first fragment of the non-informational response headers is received.
2309 EXPECT_EQ(parser.non_informational_response_start_time(),
2310 non_informational_response_start_time);
2311 // The first response start time should be earlier than the non-informational
2312 // response start time.
2313 EXPECT_LT(parser.first_response_start_time(),
2314 parser.non_informational_response_start_time());
2315
2316 // [seq=6] The parser reads the non-informational response body.
2317 auto body_buffer =
2318 base::MakeRefCounted<IOBufferWithSize>(response_body.size());
2319 int result = parser.ReadResponseBody(body_buffer.get(), response_body.size(),
2320 callback.callback());
2321 EXPECT_THAT(callback.GetResult(result), response_body.size());
2322
2323 // Check the received body.
2324 EXPECT_EQ(response_size, parser.received_bytes());
2325 }
2326
2327 // Test that an HttpStreamParser can be read from after it's received headers
2328 // and data structures owned by its owner have been deleted. This happens
2329 // when a ResponseBodyDrainer is used.
TEST(HttpStreamParser,ReadAfterUnownedObjectsDestroyed)2330 TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) {
2331 MockWrite writes[] = {
2332 MockWrite(SYNCHRONOUS, 0,
2333 "GET /foo.html HTTP/1.1\r\n\r\n"),
2334 };
2335
2336 const int kBodySize = 1;
2337 MockRead reads[] = {
2338 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"),
2339 MockRead(SYNCHRONOUS, 2, "Content-Length: 1\r\n"),
2340 MockRead(SYNCHRONOUS, 3, "Connection: Keep-Alive\r\n\r\n"),
2341 MockRead(SYNCHRONOUS, 4, "1"),
2342 MockRead(SYNCHRONOUS, 0, 5), // EOF
2343 };
2344
2345 SequencedSocketData data(reads, writes);
2346 std::unique_ptr<StreamSocket> stream_socket = CreateConnectedSocket(&data);
2347
2348 auto request_info = std::make_unique<HttpRequestInfo>();
2349 request_info->method = "GET";
2350 request_info->url = GURL("http://somewhere/foo.html");
2351
2352 scoped_refptr<GrowableIOBuffer> read_buffer =
2353 base::MakeRefCounted<GrowableIOBuffer>();
2354 HttpStreamParser parser(stream_socket.get(), false /* is_reused */,
2355 request_info.get(), read_buffer.get(),
2356 NetLogWithSource());
2357
2358 auto request_headers = std::make_unique<HttpRequestHeaders>();
2359 auto response_info = std::make_unique<HttpResponseInfo>();
2360 TestCompletionCallback callback;
2361 ASSERT_EQ(
2362 OK, parser.SendRequest("GET /foo.html HTTP/1.1\r\n", *request_headers,
2363 TRAFFIC_ANNOTATION_FOR_TESTS, response_info.get(),
2364 callback.callback()));
2365 ASSERT_THAT(parser.ReadResponseHeaders(callback.callback()), IsOk());
2366
2367 // If the object that owns the HttpStreamParser is deleted, it takes the
2368 // objects passed to the HttpStreamParser with it.
2369 request_info.reset();
2370 request_headers.reset();
2371 response_info.reset();
2372
2373 auto body_buffer = base::MakeRefCounted<IOBufferWithSize>(kBodySize);
2374 ASSERT_EQ(kBodySize, parser.ReadResponseBody(
2375 body_buffer.get(), kBodySize, callback.callback()));
2376
2377 EXPECT_EQ(CountWriteBytes(writes), parser.sent_bytes());
2378 EXPECT_EQ(CountReadBytes(reads), parser.received_bytes());
2379 }
2380
2381 // Case where one byte is received at a time.
TEST(HttpStreamParser,ReceiveOneByteAtATime)2382 TEST(HttpStreamParser, ReceiveOneByteAtATime) {
2383 const std::string kResponseHeaders =
2384 "HTTP/1.0 200 OK\r\n"
2385 "Foo: Bar\r\n\r\n";
2386 const std::string kResponseBody = "hi";
2387
2388 SimpleGetRunner get_runner;
2389 for (size_t i = 0; i < kResponseHeaders.length(); ++i) {
2390 get_runner.AddRead(std::string_view(kResponseHeaders.data() + i, 1));
2391 }
2392 for (size_t i = 0; i < kResponseBody.length(); ++i) {
2393 get_runner.AddRead(std::string_view(kResponseBody.data() + i, 1));
2394 }
2395 // EOF
2396 get_runner.AddRead("");
2397
2398 get_runner.SetupParserAndSendRequest();
2399 get_runner.ReadHeaders();
2400 std::string header_value;
2401 EXPECT_TRUE(get_runner.response_info()->headers->GetNormalizedHeader(
2402 "Foo", &header_value));
2403 EXPECT_EQ("Bar", header_value);
2404 int read_lengths[] = {1, 1, 0};
2405 EXPECT_EQ(kResponseBody,
2406 get_runner.ReadBody(kResponseBody.size(), read_lengths));
2407 }
2408
2409 } // namespace
2410
2411 } // namespace net
2412