proxygen
RFC2616.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-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 #include <stdlib.h>
13 
14 #include <folly/String.h>
15 #include <folly/ThreadLocal.h>
17 
18 namespace {
19 
20 /* Wapper around strtoul(3) */
21 bool strtoulWrapper(const char *&curs, const char *end, unsigned long& val) {
22  char* endptr = nullptr;
23 
24  unsigned long v = strtoul(curs, &endptr, 10);
25  if (endptr == curs) {
26  return false;
27  }
28 
29  if (endptr > end) {
30  return false;
31  }
32 
33  curs = endptr;
34  val = v;
35 
36  return true;
37 }
38 
39 }
40 
41 namespace proxygen { namespace RFC2616 {
42 
44  if (method == HTTPMethod::TRACE) {
46  }
47  if (method == HTTPMethod::OPTIONS || method == HTTPMethod::POST ||
48  method == HTTPMethod::PUT) {
49  return BodyAllowed::DEFINED;
50  }
52 }
53 
54 bool responseBodyMustBeEmpty(unsigned status) {
55  return (status == 304 || status == 204 ||
56  (100 <= status && status < 200));
57 }
58 
59 bool bodyImplied(const HTTPHeaders& headers) {
60  return headers.exists(HTTP_HEADER_TRANSFER_ENCODING) ||
62 }
63 
64 bool parseQvalues(folly::StringPiece value, std::vector<TokenQPair> &output) {
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 }
104 
107  unsigned long& outFirstByte,
108  unsigned long& outLastByte,
109  unsigned long& outInstanceLength) {
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 }
172 
173 }}
bool bodyImplied(const HTTPHeaders &headers)
Definition: RFC2616.cpp:59
bool responseBodyMustBeEmpty(unsigned status)
Definition: RFC2616.cpp:54
bool exists(folly::StringPiece name) const
Definition: HTTPHeaders.cpp:86
auto v
double val
Definition: String.cpp:273
void split(const Delim &delimiter, const String &input, std::vector< OutputType > &out, bool ignoreEmpty)
Definition: String-inl.h:382
BodyAllowed isRequestBodyAllowed(folly::Optional< HTTPMethod > method)
Definition: RFC2616.cpp:43
auto end(TestAdlIterable &instance)
Definition: ForeachTest.cpp:62
static const char *const value
Definition: Conv.cpp:50
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 parseByteRangeSpec(folly::StringPiece value, unsigned long &outFirstByte, unsigned long &outLastByte, unsigned long &outInstanceLength)
Definition: RFC2616.cpp:105
static const char tokens[256]
Definition: http_parser.c:184
bool parseQvalues(folly::StringPiece value, std::vector< TokenQPair > &output)
Definition: RFC2616.cpp:64