Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(760)

Side by Side Diff: net/spdy/chromium/header_coalescer.cc

Issue 2847133003: Add NetLog event for invalid Http/2 response header (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/spdy/chromium/header_coalescer.h" 5 #include "net/spdy/chromium/header_coalescer.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h"
10 #include "base/memory/ptr_util.h"
9 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/values.h"
13 #include "net/http/http_log_util.h"
10 #include "net/http/http_util.h" 14 #include "net/http/http_util.h"
11 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h" 15 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h"
12 #include "net/spdy/platform/api/spdy_string.h" 16 #include "net/spdy/platform/api/spdy_string.h"
13 17
14 namespace net { 18 namespace net {
19 namespace {
20 std::unique_ptr<base::Value> ElideNetLogHeaderCallback(
21 SpdyStringPiece header_name,
22 SpdyStringPiece header_value,
23 NetLogCaptureMode capture_mode) {
24 auto dict = base::MakeUnique<base::DictionaryValue>();
25 dict->SetString("header_name", header_name);
26 dict->SetString("header_value", ElideHeaderValueForNetLog(
27 capture_mode, header_name.as_string(),
28 header_value.as_string()));
29 return std::move(dict);
30 }
31
32 } // namespace
15 33
16 const size_t kMaxHeaderListSize = 256 * 1024; 34 const size_t kMaxHeaderListSize = 256 * 1024;
17 35
36 HeaderCoalescer::HeaderCoalescer(const NetLogWithSource& net_log)
37 : net_log_(net_log) {}
38
18 void HeaderCoalescer::OnHeader(SpdyStringPiece key, SpdyStringPiece value) { 39 void HeaderCoalescer::OnHeader(SpdyStringPiece key, SpdyStringPiece value) {
40 if (!AddHeader(key, value)) {
41 error_seen_ = true;
42 if (net_log_.IsCapturing()) {
43 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_INVALID_HEADER,
44 base::Bind(&ElideNetLogHeaderCallback, key, value));
45 }
46 }
47 }
48
49 SpdyHeaderBlock HeaderCoalescer::release_headers() {
50 DCHECK(headers_valid_);
51 headers_valid_ = false;
52 return std::move(headers_);
53 }
54
55 size_t HeaderCoalescer::EstimateMemoryUsage() const {
56 return SpdyEstimateMemoryUsage(headers_);
57 }
58
59 bool HeaderCoalescer::AddHeader(SpdyStringPiece key, SpdyStringPiece value) {
Bence 2017/04/28 18:08:35 Maybe define an enum: kOk, kEmptyName, kPseudoHead
xunjieli 2017/05/10 01:13:48 That's a bit more code that I am comfortable with
Bence 2017/05/10 12:43:29 Okay, I understand.
19 if (error_seen_) { 60 if (error_seen_) {
20 return; 61 return false;
Bence 2017/04/28 18:08:35 This will cause every header to be logged after a
xunjieli 2017/05/10 01:13:48 I have moved this conditional out of this method.
21 } 62 }
22 63
23 if (key.empty()) { 64 if (key.empty()) {
24 DVLOG(1) << "Header name must not be empty."; 65 DVLOG(1) << "Header name must not be empty.";
25 error_seen_ = true; 66 return false;
26 return;
27 } 67 }
28 68
29 SpdyStringPiece key_name = key; 69 SpdyStringPiece key_name = key;
30 if (key[0] == ':') { 70 if (key[0] == ':') {
31 if (regular_header_seen_) { 71 if (regular_header_seen_) {
32 error_seen_ = true; 72 return false;
Bence 2017/04/28 18:08:35 Is there a better mechanism to log that pseudo/reg
xunjieli 2017/05/10 01:13:47 I am not sure. We can also log every header value
Bence 2017/05/10 12:43:29 Sounds good.
33 return;
34 } 73 }
35 key_name.remove_prefix(1); 74 key_name.remove_prefix(1);
36 } else if (!regular_header_seen_) { 75 } else if (!regular_header_seen_) {
37 regular_header_seen_ = true; 76 regular_header_seen_ = true;
38 } 77 }
39 78
40 if (!HttpUtil::IsValidHeaderName(key_name)) { 79 if (!HttpUtil::IsValidHeaderName(key_name)) {
41 error_seen_ = true; 80 return false;
42 return;
43 } 81 }
44 82
45 // 32 byte overhead according to RFC 7540 Section 6.5.2. 83 // 32 byte overhead according to RFC 7540 Section 6.5.2.
46 header_list_size_ += key.size() + value.size() + 32; 84 header_list_size_ += key.size() + value.size() + 32;
47 if (header_list_size_ > kMaxHeaderListSize) { 85 if (header_list_size_ > kMaxHeaderListSize)
48 error_seen_ = true; 86 return false;
Bence 2017/04/28 18:08:35 Is there a better mechanism to log that pseudo/reg
49 return;
50 }
51 87
52 // End of line delimiter is forbidden according to RFC 7230 Section 3.2. 88 // End of line delimiter is forbidden according to RFC 7230 Section 3.2.
53 // Line folding, RFC 7230 Section 3.2.4., is a special case of this. 89 // Line folding, RFC 7230 Section 3.2.4., is a special case of this.
54 if (value.find("\r\n") != SpdyStringPiece::npos) { 90 if (value.find("\r\n") != SpdyStringPiece::npos)
55 error_seen_ = true; 91 return false;
Bence 2017/04/28 18:08:35 I'm not sure NetLog correctly displays string valu
xunjieli 2017/05/10 01:13:48 Acknowledged.
56 return;
57 }
58 92
59 auto iter = headers_.find(key); 93 auto iter = headers_.find(key);
60 if (iter == headers_.end()) { 94 if (iter == headers_.end()) {
61 headers_[key] = value; 95 headers_[key] = value;
62 } else { 96 } else {
63 // This header had multiple values, so it must be reconstructed. 97 // This header had multiple values, so it must be reconstructed.
64 SpdyStringPiece v = iter->second; 98 SpdyStringPiece v = iter->second;
65 SpdyString s(v.data(), v.length()); 99 SpdyString s(v.data(), v.length());
66 if (key == "cookie") { 100 if (key == "cookie") {
67 // Obeys section 8.1.2.5 in RFC 7540 for cookie reconstruction. 101 // Obeys section 8.1.2.5 in RFC 7540 for cookie reconstruction.
68 s.append("; "); 102 s.append("; ");
69 } else { 103 } else {
70 SpdyStringPiece("\0", 1).AppendToString(&s); 104 SpdyStringPiece("\0", 1).AppendToString(&s);
71 } 105 }
72 value.AppendToString(&s); 106 value.AppendToString(&s);
73 headers_[key] = s; 107 headers_[key] = s;
74 } 108 }
109 return true;
75 } 110 }
76 111
77 SpdyHeaderBlock HeaderCoalescer::release_headers() {
78 DCHECK(headers_valid_);
79 headers_valid_ = false;
80 return std::move(headers_);
81 }
82
83 size_t HeaderCoalescer::EstimateMemoryUsage() const {
84 return SpdyEstimateMemoryUsage(headers_);
85 }
86 112
87 } // namespace net 113 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698