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
14namespace {
15
17const std::string crlf = "\r\n";
18
19}
20
21namespace isc {
22namespace http {
23
25 : HttpMessage(INBOUND), required_methods_(),
26 method_(Method::HTTP_METHOD_UNKNOWN),
27 context_(new HttpRequestContext()) {
28}
29
30HttpRequest::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
41void
43 required_methods_.insert(method);
44}
45
46void
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.
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
114void
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
125void
127 created_ = false;
128 finalized_ = false;
130 headers_.clear();
131}
132
135 checkCreated();
136 return (method_);
137}
138
139std::string
141 checkCreated();
142 return (context_->uri_);
143}
144
145std::string
148 return (context_->body_);
149}
150
151std::string
154
155 std::ostringstream s;
156 s << methodToString(getMethod()) << " " << getUri() << " HTTP/" <<
158 return (s.str());
159}
160
161std::string
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
182bool
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
199
200 return (((ver == HttpVersion::HTTP_10()) && (conn_value == "keep-alive")) ||
201 ((HttpVersion::HTTP_10() < ver) && (conn_value.empty() || (conn_value != "close"))));
202}
203
205HttpRequest::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
226std::string
228 switch (method) {
229 case Method::HTTP_GET:
230 return ("GET");
232 return ("POST");
234 return ("HEAD");
235 case Method::HTTP_PUT:
236 return ("PUT");
238 return ("DELETE");
240 return ("OPTIONS");
242 return ("CONNECT");
243 default:
244 return ("unknown HTTP method");
245 }
246}
247
248}
249}
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Represents HTTP header including a header name and value.
Definition: http_header.h:20
Base class for HttpRequest and HttpResponse.
Definition: http_message.h:62
HttpHeaderMap headers_
Parsed HTTP headers.
Definition: http_message.h:259
HttpVersion http_version_
HTTP version numbers.
Definition: http_message.h:238
HttpVersion getHttpVersion() const
Returns HTTP version number (major and minor).
Definition: http_message.cc:54
void checkFinalized() const
Checks if the finalize was called.
Definition: http_message.cc:99
void checkCreated() const
Checks if the create was called.
Definition: http_message.cc:90
bool created_
Flag indicating whether create was called.
Definition: http_message.h:253
std::set< HttpVersion > required_versions_
Set of required HTTP versions.
Definition: http_message.h:235
Direction getDirection() const
Returns HTTP message direction.
Definition: http_message.h:80
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
HttpHeaderPtr getHeader(const std::string &header_name) const
Returns object encapsulating HTTP header.
Definition: http_message.cc:60
bool finalized_
Flag indicating whether finalize was called.
Definition: http_message.h:256
HttpHeaderMap required_headers_
Map holding required HTTP headers.
Definition: http_message.h:250
Generic exception thrown by HttpRequest class.
Definition: request.h:19
Method methodFromString(std::string method) const
Converts HTTP method specified in textual format to Method.
Definition: request.cc:205
Method
HTTP methods.
Definition: request.h:52
HttpRequestContextPtr context_
Pointer to the HttpRequestContext holding parsed data.
Definition: request.h:171
std::string toBriefString() const
Returns HTTP method, URI and HTTP version as a string.
Definition: request.cc:152
virtual void finalize()
Completes creation of the HTTP request.
Definition: request.cc:115
Method getMethod() const
Returns HTTP method of the request.
Definition: request.cc:134
virtual void create()
Commits information held in the context into the request.
Definition: request.cc:47
std::string getBody() const
Returns HTTP message body as string.
Definition: request.cc:146
bool isPersistent() const
Checks if the client has requested persistent connection.
Definition: request.cc:183
void requireHttpMethod(const HttpRequest::Method &method)
Specifies an HTTP method allowed for the request.
Definition: request.cc:42
HttpRequest()
Constructor for inbound HTTP request.
Definition: request.cc:24
std::string getUri() const
Returns HTTP request URI.
Definition: request.cc:140
std::set< Method > required_methods_
Set of required HTTP methods.
Definition: request.h:164
const HttpRequestContextPtr & context() const
Returns pointer to the HttpRequestContext.
Definition: request.h:80
std::string methodToString(const HttpRequest::Method &method) const
Converts HTTP method to string.
Definition: request.cc:227
Method method_
HTTP method of the request.
Definition: request.h:167
virtual void reset()
Reset the state of the object.
Definition: request.cc:126
virtual std::string toString() const
Returns HTTP message as string.
Definition: request.cc:162
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
int version()
returns Kea hooks version.
boost::shared_ptr< HttpHeader > HttpHeaderPtr
Pointer to the HttpHeader class.
Definition: http_header.h:65
Defines the logger used by the top-level component of kea-dhcp-ddns.
HTTP request context.
HTTP protocol version.
Definition: http_types.h:14
unsigned minor_
Minor HTTP version.
Definition: http_types.h:16
static const HttpVersion & HTTP_10()
HTTP version 1.0.
Definition: http_types.h:53
unsigned major_
Major HTTP version.
Definition: http_types.h:15