proxygen
HeaderDecodeInfo.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
11 
12 using std::string;
13 
14 namespace proxygen {
15 
17  const folly::fbstring& value) {
18  // Refuse decoding other headers if an error is already found
20  || parsingError != "") {
21  VLOG(4) << "Ignoring header=" << name << " value=" << value <<
22  " due to parser error=" << parsingError;
23  return true;
24  }
25  VLOG(5) << "Processing header=" << name << " value=" << value;
26  folly::StringPiece nameSp(name);
27  folly::StringPiece valueSp(value);
28 
29  if (nameSp.startsWith(':')) {
30  pseudoHeaderSeen_ = true;
31  if (regularHeaderSeen_) {
32  parsingError = folly::to<string>("Illegal pseudo header name=", nameSp);
33  return false;
34  }
35  if (isRequest_) {
36  if (nameSp == headers::kMethod) {
37  if (!verifier.setMethod(valueSp)) {
38  return false;
39  }
40  } else if (nameSp == headers::kScheme) {
41  if (!verifier.setScheme(valueSp)) {
42  return false;
43  }
44  } else if (nameSp == headers::kAuthority) {
45  if (!verifier.setAuthority(valueSp)) {
46  return false;
47  }
48  } else if (nameSp == headers::kPath) {
49  if (!verifier.setPath(valueSp)) {
50  return false;
51  }
52  } else if (nameSp == headers::kProtocol) {
53  if (!verifier.setUpgradeProtocol(valueSp)) {
54  return false;
55  }
56  } else {
57  parsingError = folly::to<string>("Invalid req header name=", nameSp);
58  return false;
59  }
60  } else {
61  if (nameSp == headers::kStatus) {
62  if (hasStatus_) {
63  parsingError = string("Duplicate status");
64  return false;
65  }
66  hasStatus_ = true;
67  int32_t code = -1;
68  folly::tryTo<int32_t>(valueSp).then(
69  [&code](int32_t num) { code = num; });
70  if (code >= 100 && code <= 999) {
71  msg->setStatusCode(code);
72  msg->setStatusMessage(HTTPMessage::getDefaultReason(code));
73  } else {
74  parsingError = folly::to<string>("Malformed status code=", valueSp);
75  return false;
76  }
77  } else {
78  parsingError = folly::to<string>("Invalid resp header name=", nameSp);
79  return false;
80  }
81  }
82  } else {
83  regularHeaderSeen_ = true;
84  if (nameSp == "connection") {
85  parsingError = string("HTTP/2 Message with Connection header");
86  return false;
87  }
88  if (nameSp == "content-length") {
89  uint32_t cl = 0;
90  folly::tryTo<uint32_t>(valueSp).then(
91  [&cl](uint32_t num) { cl = num; });
92  if (contentLength_ && *contentLength_ != cl) {
93  parsingError = string("Multiple content-length headers");
94  return false;
95  }
96  contentLength_ = cl;
97  }
98  bool nameOk = CodecUtil::validateHeaderName(nameSp);
99  bool valueOk = CodecUtil::validateHeaderValue(valueSp, CodecUtil::STRICT);
100  if (!nameOk || !valueOk) {
101  parsingError = folly::to<string>("Bad header value: name=",
102  nameSp, " value=", valueSp);
103  return false;
104  }
105  // Add the (name, value) pair to headers
106  msg->getHeaders().add(nameSp, valueSp);
107  }
108  return true;
109 }
110 
112  HTTPHeaders& headers = msg->getHeaders();
113 
114  if (isRequest_ && !isRequestTrailers_) {
115  auto combinedCookie = headers.combine(HTTP_HEADER_COOKIE, "; ");
116  if (!combinedCookie.empty()) {
117  headers.set(HTTP_HEADER_COOKIE, combinedCookie);
118  }
119  if (!verifier.validate()) {
121  return;
122  }
123  }
124 
125  bool isResponseTrailers = (!isRequest_ && !hasStatus_);
126  if ((isRequestTrailers_ || isResponseTrailers) && pseudoHeaderSeen_) {
127  parsingError = "Pseudo headers forbidden in trailers.";
128  return;
129  }
130 
131  msg->setHTTPVersion(1, 1);
132  msg->setIngressHeaderSize(decodedSize);
133 }
134 
136  return hasStatus_;
137 }
138 }
const std::string kProtocol
bool setUpgradeProtocol(folly::StringPiece protocol)
static bool validateHeaderName(folly::ByteRange name)
Definition: CodecUtil.h:43
std::unique_ptr< HTTPMessage > msg
bool setScheme(folly::StringPiece scheme)
std::string combine(const T &header, const std::string &separator=COMBINE_SEPARATOR) const
Definition: HTTPHeaders.h:382
HPACK::DecodeError decodeError
folly::Optional< uint32_t > contentLength_
const std::string kScheme
const char * name
Definition: http_parser.c:437
void set(folly::StringPiece name, const std::string &value)
Definition: HTTPHeaders.h:119
bool setMethod(folly::StringPiece method)
bool onHeader(const folly::fbstring &name, const folly::fbstring &value)
static const char *const value
Definition: Conv.cpp:50
bool startsWith(const const_range_type &other) const
Definition: Range.h:828
const char * string
Definition: Conv.cpp:212
const std::string kStatus
const std::string kPath
bool setAuthority(folly::StringPiece authority)
static bool validateHeaderValue(folly::ByteRange value, CtlEscapeMode mode)
Definition: CodecUtil.h:66
static const char * getDefaultReason(uint16_t status)
const std::string kAuthority
void onHeadersComplete(HTTPHeaderSize decodedSize)
bool setPath(folly::StringPiece path)
const std::string kMethod
HTTPRequestVerifier verifier