Kea  1.5.0
request.cc
Go to the documentation of this file.
1 // Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <http/request.h>
10 #include <boost/algorithm/string.hpp>
11 #include <boost/lexical_cast.hpp>
12 #include <sstream>
13 
14 namespace {
15 
17 const std::string crlf = "\r\n";
18 
19 }
20 
21 namespace isc {
22 namespace http {
23 
25  : HttpMessage(INBOUND), required_methods_(),
26  method_(Method::HTTP_METHOD_UNKNOWN),
27  context_(new HttpRequestContext()) {
28 }
29 
30 HttpRequest::HttpRequest(const Method& method, const std::string& uri,
31  const HttpVersion& version)
32  : HttpMessage(OUTBOUND), required_methods_(),
33  method_(Method::HTTP_METHOD_UNKNOWN),
34  context_(new HttpRequestContext()) {
35  context()->method_ = methodToString(method);
36  context()->uri_ = uri;
37  context()->http_version_major_ = version.major_;
38  context()->http_version_minor_ = version.minor_;
39 }
40 
41 void
43  required_methods_.insert(method);
44 }
45 
46 void
48  try {
49  // The RequestParser doesn't validate the method name. Thus, this
50  // may throw an exception. But, we're fine with lower case names,
51  // e.g. get, post etc.
52  method_ = methodFromString(context_->method_);
53 
54  // Check if the method is allowed for this request.
56  isc_throw(BadValue, "use of HTTP " << methodToString(method_)
57  << " not allowed");
58  }
59 
60  http_version_.major_ = context_->http_version_major_;
61  http_version_.minor_ = context_->http_version_minor_;
62 
63  // Check if the HTTP version is allowed for this request.
65  isc_throw(BadValue, "use of HTTP version "
66  << http_version_.major_ << "."
68  << " not allowed");
69  }
70 
71  // Copy headers from the context.
72  for (auto header = context_->headers_.begin();
73  header != context_->headers_.end();
74  ++header) {
75  HttpHeaderPtr hdr(new HttpHeader(header->name_, header->value_));
76  headers_[hdr->getLowerCaseName()] = hdr;
77  }
78 
80  HttpHeaderPtr hdr(new HttpHeader("Content-Length",
81  boost::lexical_cast<std::string>(context_->body_.length())));
82  headers_["content-length"] = hdr;
83  }
84 
85  // Iterate over required headers and check that they exist
86  // in the HTTP request.
87  for (auto req_header = required_headers_.begin();
88  req_header != required_headers_.end();
89  ++req_header) {
90  auto header = headers_.find(req_header->first);
91  if (header == headers_.end()) {
92  isc_throw(BadValue, "required header " << req_header->first
93  << " not found in the HTTP request");
94  } else if (!req_header->second->getValue().empty() &&
95  !header->second->isValueEqual(req_header->second->getValue())) {
96  // If specific value is required for the header, check
97  // that the value in the HTTP request matches it.
98  isc_throw(BadValue, "required header's " << header->first
99  << " value is " << req_header->second->getValue()
100  << ", but " << header->second->getValue() << " was found");
101  }
102  }
103 
104  } catch (const std::exception& ex) {
105  // Reset the state of the object if we failed at any point.
106  reset();
108  }
109 
110  // All ok.
111  created_ = true;
112 }
113 
114 void
116  if (!created_) {
117  create();
118  }
119 
120  // Copy the body from the context. Derive classes may further
121  // interpret the body contents, e.g. against the Content-Type.
122  finalized_ = true;
123 }
124 
125 void
127  created_ = false;
128  finalized_ = false;
130  headers_.clear();
131 }
132 
135  checkCreated();
136  return (method_);
137 }
138 
139 std::string
141  checkCreated();
142  return (context_->uri_);
143 }
144 
145 std::string
147  checkFinalized();
148  return (context_->body_);
149 }
150 
151 std::string
153  checkFinalized();
154 
155  std::ostringstream s;
156  s << methodToString(getMethod()) << " " << getUri() << " HTTP/" <<
158  return (s.str());
159 }
160 
161 std::string
163  checkFinalized();
164 
165  std::ostringstream s;
166  // HTTP method, URI and version number.
167  s << toBriefString() << crlf;
168 
169  for (auto header_it = headers_.cbegin(); header_it != headers_.cend();
170  ++header_it) {
171  s << header_it->second->getName() << ": " << header_it->second->getValue()
172  << crlf;
173  }
174 
175  s << crlf;
176 
177  s << getBody();
178 
179  return (s.str());
180 }
181 
182 bool
184  HttpHeaderPtr conn;
185 
186  try {
187  conn = getHeader("connection");
188 
189  } catch (...) {
190  // If there is an exception, it means that the header was not found.
191  }
192 
193  std::string conn_value;
194  if (conn) {
195  conn_value = conn->getLowerCaseValue();
196  }
197 
198  HttpVersion ver = getHttpVersion();
199 
200  return (((ver == HttpVersion::HTTP_10()) && (conn_value == "keep-alive")) ||
201  ((HttpVersion::HTTP_10() < ver) && (conn_value.empty() || (conn_value != "close"))));
202 }
203 
205 HttpRequest::methodFromString(std::string method) const {
206  boost::to_upper(method);
207  if (method == "GET") {
208  return (Method::HTTP_GET);
209  } else if (method == "POST") {
210  return (Method::HTTP_POST);
211  } else if (method == "HEAD") {
212  return (Method::HTTP_HEAD);
213  } else if (method == "PUT") {
214  return (Method::HTTP_PUT);
215  } else if (method == "DELETE") {
216  return (Method::HTTP_DELETE);
217  } else if (method == "OPTIONS") {
218  return (Method::HTTP_OPTIONS);
219  } else if (method == "CONNECT") {
220  return (Method::HTTP_CONNECT);
221  } else {
222  isc_throw(HttpRequestError, "unknown HTTP method " << method);
223  }
224 }
225 
226 std::string
228  switch (method) {
229  case Method::HTTP_GET:
230  return ("GET");
231  case Method::HTTP_POST:
232  return ("POST");
233  case Method::HTTP_HEAD:
234  return ("HEAD");
235  case Method::HTTP_PUT:
236  return ("PUT");
237  case Method::HTTP_DELETE:
238  return ("DELETE");
240  return ("OPTIONS");
242  return ("CONNECT");
243  default:
244  return ("unknown HTTP method");
245  }
246 }
247 
248 }
249 }
isc::http::HttpMessage::checkCreated
void checkCreated() const
Checks if the create was called.
Definition: http_message.cc:90
isc::http::HttpMessage::checkFinalized
void checkFinalized() const
Checks if the finalize was called.
Definition: http_message.cc:99
isc::http::HttpHeader
Represents HTTP header including a header name and value.
Definition: http_header.h:20
isc::http::HttpRequest::reset
virtual void reset()
Reset the state of the object.
Definition: request.cc:126
isc::http::HttpMessage::required_versions_
std::set< HttpVersion > required_versions_
Set of required HTTP versions.
Definition: http_message.h:235
version
int version()
returns Kea hooks version.
Definition: high_availability/version.cc:13
isc::http::HttpRequest::Method::HTTP_OPTIONS
@ HTTP_OPTIONS
isc::http::HttpRequest::getMethod
Method getMethod() const
Returns HTTP method of the request.
Definition: request.cc:134
isc::http::HttpRequest::Method::HTTP_PUT
@ HTTP_PUT
isc::http::HttpMessage::getHeader
HttpHeaderPtr getHeader(const std::string &header_name) const
Returns object encapsulating HTTP header.
Definition: http_message.cc:60
isc::http::HttpRequest::context_
HttpRequestContextPtr context_
Pointer to the HttpRequestContext holding parsed data.
Definition: request.h:171
isc::http::HttpRequest::required_methods_
std::set< Method > required_methods_
Set of required HTTP methods.
Definition: request.h:164
isc::http::HttpMessage::headers_
HttpHeaderMap headers_
Parsed HTTP headers.
Definition: http_message.h:259
isc::http::HttpRequest::Method::HTTP_HEAD
@ HTTP_HEAD
isc::http::HttpRequest::methodFromString
Method methodFromString(std::string method) const
Converts HTTP method specified in textual format to Method.
Definition: request.cc:205
isc::http::HttpVersion
HTTP protocol version.
Definition: http_types.h:14
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::http::HttpRequestError
Generic exception thrown by HttpRequest class.
Definition: request.h:19
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition: exceptions/exceptions.cc:32
isc::http::HttpRequest::HttpRequest
HttpRequest()
Constructor for inbound HTTP request.
Definition: request.cc:24
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::http::HttpRequest::method_
Method method_
HTTP method of the request.
Definition: request.h:167
isc::http::HttpRequest::toString
virtual std::string toString() const
Returns HTTP message as string.
Definition: request.cc:162
isc::http::HttpVersion::major_
unsigned major_
Major HTTP version.
Definition: http_types.h:15
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: exceptions/exceptions.h:132
isc::http::HttpMessage
Base class for HttpRequest and HttpResponse.
Definition: http_message.h:62
isc::http::HttpRequestContext
HTTP request context.
Definition: request_context.h:23
isc::http::HttpRequest::methodToString
std::string methodToString(const HttpRequest::Method &method) const
Converts HTTP method to string.
Definition: request.cc:227
isc::http::HttpRequest::Method::HTTP_METHOD_UNKNOWN
@ HTTP_METHOD_UNKNOWN
isc::http::HttpVersion::HTTP_10
static const HttpVersion & HTTP_10()
HTTP version 1.0.
Definition: http_types.h:53
isc::http::HttpMessage::created_
bool created_
Flag indicating whether create was called.
Definition: http_message.h:253
isc::http::HttpRequest::Method::HTTP_DELETE
@ HTTP_DELETE
isc::http::HttpMessage::http_version_
HttpVersion http_version_
HTTP version numbers.
Definition: http_message.h:238
request.h
isc::http::HttpRequest::getBody
std::string getBody() const
Returns HTTP message body as string.
Definition: request.cc:146
isc::http::HttpHeaderPtr
boost::shared_ptr< HttpHeader > HttpHeaderPtr
Pointer to the HttpHeader class.
Definition: http_header.h:65
isc::http::HttpRequest::isPersistent
bool isPersistent() const
Checks if the client has requested persistent connection.
Definition: request.cc:183
isc::http::HttpMessage::getDirection
Direction getDirection() const
Returns HTTP message direction.
Definition: http_message.h:80
isc::http::HttpRequest::Method::HTTP_POST
@ HTTP_POST
isc::http::HttpMessage::required_headers_
HttpHeaderMap required_headers_
Map holding required HTTP headers.
Definition: http_message.h:250
isc::http::HttpMessage::inRequiredSet
bool inRequiredSet(const T &element, const std::set< T > &element_set) const
Checks if the set is empty or the specified element belongs to this set.
Definition: http_message.h:224
isc::http::HttpRequest::requireHttpMethod
void requireHttpMethod(const HttpRequest::Method &method)
Specifies an HTTP method allowed for the request.
Definition: request.cc:42
isc::http::HttpRequest::Method::HTTP_CONNECT
@ HTTP_CONNECT
isc::http::HttpVersion::minor_
unsigned minor_
Minor HTTP version.
Definition: http_types.h:16
isc::http::HttpMessage::getHttpVersion
HttpVersion getHttpVersion() const
Returns HTTP version number (major and minor).
Definition: http_message.cc:54
isc::http::HttpMessage::finalized_
bool finalized_
Flag indicating whether finalize was called.
Definition: http_message.h:256
isc::http::HttpMessage::OUTBOUND
@ OUTBOUND
Definition: http_message.h:68
isc::http::HttpRequest::context
const HttpRequestContextPtr & context() const
Returns pointer to the HttpRequestContext.
Definition: request.h:80
isc::http::HttpRequest::finalize
virtual void finalize()
Completes creation of the HTTP request.
Definition: request.cc:115
isc::http::HttpRequest::create
virtual void create()
Commits information held in the context into the request.
Definition: request.cc:47
isc::http::HttpRequest::toBriefString
std::string toBriefString() const
Returns HTTP method, URI and HTTP version as a string.
Definition: request.cc:152
isc::http::HttpRequest::Method
Method
HTTP methods.
Definition: request.h:52
isc::http::HttpRequest::Method::HTTP_GET
@ HTTP_GET
isc::http::HttpRequest::getUri
std::string getUri() const
Returns HTTP request URI.
Definition: request.cc:140