proxygen
proxygen::RFC2616 Namespace Reference

Typedefs

using TokenQPair = std::pair< folly::StringPiece, double >
 

Enumerations

enum  BodyAllowed { BodyAllowed::DEFINED, BodyAllowed::NOT_DEFINED, BodyAllowed::NOT_ALLOWED }
 

Functions

BodyAllowed isRequestBodyAllowed (folly::Optional< HTTPMethod > method)
 
bool responseBodyMustBeEmpty (unsigned status)
 
bool bodyImplied (const HTTPHeaders &headers)
 
bool parseQvalues (folly::StringPiece value, std::vector< TokenQPair > &output)
 
bool parseByteRangeSpec (folly::StringPiece value, unsigned long &outFirstByte, unsigned long &outLastByte, unsigned long &outInstanceLength)
 

Typedef Documentation

using proxygen::RFC2616::TokenQPair = typedef std::pair<folly::StringPiece, double>

Parse a string containing tokens and qvalues, such as the RFC strings for Accept-Charset, Accept-Encoding and Accept-Language. It won't work for complex Accept: headers because it doesn't return parameters or accept-extension.

See RFC sections 14.2, 14.3, 14.4 for definitions of these header values

TODO: optionally sort by qvalue descending

Return true if the string was well formed according to the RFC. Note it can return false but still populate output with best-effort parsing.

Definition at line 69 of file RFC2616.h.

Enumeration Type Documentation

This file contains functions for determining when certain tricky parts of RFC 2616 arise. The HTTP request as defined in RFC 2616 may or may not have a body. In some cases they MUST NOT have a body. In other cases, the body has no semantic meaning and so is not defined. Finally, for some methods, the body is well defined. Please see Section 9 and 4.3 for details on this.

Enumerator
DEFINED 
NOT_DEFINED 
NOT_ALLOWED 

Definition at line 34 of file RFC2616.h.

Function Documentation

bool proxygen::RFC2616::bodyImplied ( const HTTPHeaders headers)

Returns true if the headers imply that a body will follow. Note that in some situations a body may come even if this function returns false (e.g. a 1.0 response body's length can be given implicitly by closing the connection).

Definition at line 59 of file RFC2616.cpp.

References proxygen::HTTPHeaders::exists(), proxygen::HTTP_HEADER_CONTENT_LENGTH, and proxygen::HTTP_HEADER_TRANSFER_ENCODING.

Referenced by proxygen::HTTPChecks::generateHeader(), and proxygen::HTTPChecks::onHeadersComplete().

BodyAllowed proxygen::RFC2616::isRequestBodyAllowed ( folly::Optional< HTTPMethod method)

Definition at line 43 of file RFC2616.cpp.

References DEFINED, NOT_ALLOWED, NOT_DEFINED, proxygen::OPTIONS, proxygen::POST, proxygen::PUT, and proxygen::TRACE.

Referenced by proxygen::HTTPChecks::generateHeader(), and proxygen::HTTPChecks::onHeadersComplete().

43  {
44  if (method == HTTPMethod::TRACE) {
45  return BodyAllowed::NOT_ALLOWED;
46  }
47  if (method == HTTPMethod::OPTIONS || method == HTTPMethod::POST ||
48  method == HTTPMethod::PUT) {
49  return BodyAllowed::DEFINED;
50  }
51  return BodyAllowed::NOT_DEFINED;
52 }
bool proxygen::RFC2616::parseByteRangeSpec ( folly::StringPiece  value,
unsigned long &  firstByte,
unsigned long &  lastByte,
unsigned long &  instanceLength 
)

Parse an RFC 2616 section 14.16 "bytes A-B/C" string and returns them as the first and last bytes and instance length, respectively.

Wildcards are handled specially as follows: if the range is actually "*", the first byte is parsed as 0 and last byte as ULONG_MAX; if instance length is actually "*", it is parsed as ULONG_MAX.

Note that is ONLY suitable for use in parsing "Content-Range" response headers. The "Range" request header has different but similar syntax.

Definition at line 105 of file RFC2616.cpp.

References folly::Range< Iter >::begin(), folly::Range< Iter >::end(), and folly::Range< Iter >::startsWith().

Referenced by TEST().

109  {
110  // We should start with "bytes "
111  if (!value.startsWith("bytes ")) {
112  return false;
113  }
114 
115  const char* curs = value.begin() + 6 /* strlen("bytes ") */;
116  const char* end = value.end();
117 
118  unsigned long firstByte = ULONG_MAX;
119  unsigned long lastByte = ULONG_MAX;
120  unsigned long instanceLength = ULONG_MAX;
121 
122  if (!strtoulWrapper(curs, end, firstByte)) {
123  if (*curs != '*') {
124  return false;
125  }
126 
127  firstByte = 0;
128  lastByte = ULONG_MAX;
129  ++curs;
130  } else {
131  if (*curs != '-') {
132  return false;
133  }
134 
135  ++curs;
136 
137  if (!strtoulWrapper(curs, end, lastByte)) {
138  return false;
139  }
140  }
141 
142  if (*curs != '/') {
143  return false;
144  }
145 
146  ++curs;
147  if (*curs != '*') {
148  if (!strtoulWrapper(curs, end, instanceLength)) {
149  return false;
150  }
151  } else {
152  ++curs;
153  }
154 
155  if (curs < end && *curs != '\0') {
156  return false;
157  }
158 
159  if (lastByte < firstByte) {
160  return false;
161  }
162 
163  if ((lastByte - firstByte + 1) > instanceLength) {
164  return false;
165  }
166 
167  outFirstByte = firstByte;
168  outLastByte = lastByte;
169  outInstanceLength = instanceLength;
170  return true;
171 }
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
constexpr Iter end() const
Definition: Range.h:455
constexpr Iter begin() const
Definition: Range.h:452
bool startsWith(const const_range_type &other) const
Definition: Range.h:828
bool proxygen::RFC2616::parseQvalues ( folly::StringPiece  value,
std::vector< TokenQPair > &  output 
)

Definition at line 64 of file RFC2616.cpp.

References folly::split(), and tokens.

Referenced by proxygen::ZlibServerFilterFactory::acceptsSupportedCompressionType(), proxygen::CodecUtil::hasGzipAndDeflate(), and TEST().

64  {
65  bool result = true;
67  tokens->clear();
68  folly::split(",", value, *tokens, true /*ignore empty*/);
69  for (auto& token: *tokens) {
70  auto pos = token.find(';');
71  double qvalue = 1.0;
72  if (pos != std::string::npos) {
73  auto qpos = token.find("q=", pos);
74  if (qpos != std::string::npos) {
75  folly::StringPiece qvalueStr(token.data() + qpos + 2,
76  token.size() - (qpos + 2));
77  try {
78  qvalue = folly::to<double>(&qvalueStr);
79  } catch (const std::range_error&) {
80  // q=<some garbage>
81  result = false;
82  }
83  // we could validate that the remainder of qvalueStr was all whitespace,
84  // for now we just discard it
85  } else {
86  // ; but no q=
87  result = false;
88  }
89  token.reset(token.start(), pos);
90  }
91  // strip leading whitespace
92  while (token.size() > 0 && isspace(token[0])) {
93  token.reset(token.start() + 1, token.size() - 1);
94  }
95  if (token.size() == 0) {
96  // empty token
97  result = false;
98  } else {
99  output.emplace_back(token, qvalue);
100  }
101  }
102  return result && output.size() > 0;
103 }
void split(const Delim &delimiter, const String &input, std::vector< OutputType > &out, bool ignoreEmpty)
Definition: String-inl.h:382
static const char tokens[256]
Definition: http_parser.c:184
bool proxygen::RFC2616::responseBodyMustBeEmpty ( unsigned  status)

Some status codes imply that there MUST NOT be a response body. See section 4.3: "All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body."

Parameters
statusThe code to test (100 <= status <= 999)

Definition at line 54 of file RFC2616.cpp.

Referenced by proxygen::HTTP1xCodec::generateHeader(), proxygen::HTTP1xCodec::onHeadersComplete(), and proxygen::HTTPTransaction::onIngressHeadersComplete().

54  {
55  return (status == 304 || status == 204 ||
56  (100 <= status && status < 200));
57 }