Kea 2.5.7
request.cc
Go to the documentation of this file.
1// Copyright (C) 2016-2024 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
27
29
31 : HttpMessage(INBOUND), required_methods_(),
32 method_(Method::HTTP_METHOD_UNKNOWN),
33 context_(new HttpRequestContext()),
34 remote_(""), tls_(false), subject_(""), issuer_(""),
35 basic_auth_(""), custom_("") {
36}
37
39 const std::string& uri,
40 const HttpVersion& version,
41 const HostHttpHeader& host_header,
42 const BasicHttpAuthPtr& basic_auth)
43 : HttpMessage(OUTBOUND), required_methods_(),
44 method_(Method::HTTP_METHOD_UNKNOWN),
45 context_(new HttpRequestContext()),
46 remote_(""), tls_(false), subject_(""), issuer_(""),
47 basic_auth_(""), custom_("") {
48 context()->method_ = methodToString(method);
49 context()->uri_ = uri;
50 context()->http_version_major_ = version.major_;
51 context()->http_version_minor_ = version.minor_;
52 // The Host header is mandatory in HTTP/1.1 and should be placed before
53 // any other headers. We also include it for HTTP/1.0 as it doesn't
54 // harm to include it.
55 context()->headers_.push_back(HttpHeaderContext(host_header.getName(),
56 host_header.getValue()));
57 if (basic_auth) {
58 context()->headers_.push_back(BasicAuthHttpHeaderContext(*basic_auth));
59 }
60}
61
62void
64 required_methods_.insert(method);
65}
66
67void
69 try {
70 // The RequestParser doesn't validate the method name. Thus, this
71 // may throw an exception. But, we're fine with lower case names,
72 // e.g. get, post etc.
74
75 // Check if the method is allowed for this request.
77 isc_throw(BadValue, "use of HTTP " << methodToString(method_)
78 << " not allowed");
79 }
80
81 http_version_.major_ = context_->http_version_major_;
82 http_version_.minor_ = context_->http_version_minor_;
83
84 // Check if the HTTP version is allowed for this request.
86 isc_throw(BadValue, "use of HTTP version "
87 << http_version_.major_ << "."
89 << " not allowed");
90 }
91
92 // Copy headers from the context.
93 for (auto const& header : context_->headers_) {
94 HttpHeaderPtr hdr(new HttpHeader(header.name_, header.value_));
95 headers_[hdr->getLowerCaseName()] = hdr;
96 }
97
99 HttpHeaderPtr hdr(new HttpHeader("Content-Length",
100 boost::lexical_cast<std::string>(context_->body_.length())));
101 headers_["content-length"] = hdr;
102 }
103
104 // Iterate over required headers and check that they exist
105 // in the HTTP request.
106 for (auto const& req_header : required_headers_) {
107 auto header = headers_.find(req_header.first);
108 if (header == headers_.end()) {
109 isc_throw(BadValue, "required header " << req_header.first
110 << " not found in the HTTP request");
111 } else if (!req_header.second->getValue().empty() &&
112 !header->second->isValueEqual(req_header.second->getValue())) {
113 // If specific value is required for the header, check
114 // that the value in the HTTP request matches it.
115 isc_throw(BadValue, "required header's " << header->first
116 << " value is " << req_header.second->getValue()
117 << ", but " << header->second->getValue() << " was found");
118 }
119 }
120
121 } catch (const std::exception& ex) {
122 // Reset the state of the object if we failed at any point.
123 reset();
125 }
126
127 // All ok.
128 created_ = true;
129}
130
131void
133 if (!created_) {
134 create();
135 }
136
137 // Copy the body from the context. Derive classes may further
138 // interpret the body contents, e.g. against the Content-Type.
139 finalized_ = true;
140}
141
142void
144 created_ = false;
145 finalized_ = false;
147 headers_.clear();
148}
149
152 checkCreated();
153 return (method_);
154}
155
156std::string
158 checkCreated();
159 return (context_->uri_);
160}
161
162std::string
165 return (context_->body_);
166}
167
168std::string
171
172 std::ostringstream s;
173 s << methodToString(getMethod()) << " " << getUri() << " HTTP/" <<
175 return (s.str());
176}
177
178std::string
181
182 std::ostringstream s;
183 // HTTP method, URI and version number.
184 s << toBriefString() << crlf;
185
186 // Host header must go first.
187 HttpHeaderPtr host_header;
188 try {
189 host_header = getHeader("Host");
190 if (host_header) {
191 s << host_header->getName() << ": " << host_header->getValue() << crlf;
192 }
193
194 } catch (...) {
195 // impossible condition
196 }
197
198 // Add all other headers.
199 for (auto const& header_it : headers_) {
200 if (header_it.second->getName() != "Host") {
201 s << header_it.second->getName() << ": " << header_it.second->getValue()
202 << crlf;
203 }
204 }
205
206 s << crlf;
207
208 s << getBody();
209
210 return (s.str());
211}
212
213bool
215 HttpHeaderPtr conn;
216
217 try {
218 conn = getHeader("connection");
219
220 } catch (...) {
221 // If there is an exception, it means that the header was not found.
222 }
223
224 std::string conn_value;
225 if (conn) {
226 conn_value = conn->getLowerCaseValue();
227 }
228
230
231 return (((ver == HttpVersion::HTTP_10()) && (conn_value == "keep-alive")) ||
232 ((HttpVersion::HTTP_10() < ver) && (conn_value.empty() || (conn_value != "close"))));
233}
234
236HttpRequest::methodFromString(std::string method) const {
237 boost::to_upper(method);
238 if (method == "GET") {
239 return (Method::HTTP_GET);
240 } else if (method == "POST") {
241 return (Method::HTTP_POST);
242 } else if (method == "HEAD") {
243 return (Method::HTTP_HEAD);
244 } else if (method == "PUT") {
245 return (Method::HTTP_PUT);
246 } else if (method == "DELETE") {
247 return (Method::HTTP_DELETE);
248 } else if (method == "OPTIONS") {
249 return (Method::HTTP_OPTIONS);
250 } else if (method == "CONNECT") {
251 return (Method::HTTP_CONNECT);
252 } else {
253 isc_throw(HttpRequestError, "unknown HTTP method " << method);
254 }
255}
256
257std::string
259 switch (method) {
260 case Method::HTTP_GET:
261 return ("GET");
263 return ("POST");
265 return ("HEAD");
266 case Method::HTTP_PUT:
267 return ("PUT");
269 return ("DELETE");
271 return ("OPTIONS");
273 return ("CONNECT");
274 default:
275 return ("unknown HTTP method");
276 }
277}
278
279}
280}
int version()
returns Kea hooks version.
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 Host header.
Definition: http_header.h:68
Represents HTTP header including a header name and value.
Definition: http_header.h:20
std::string getName() const
Returns header name.
Definition: http_header.h:31
std::string getValue() const
Returns header value.
Definition: http_header.h:36
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:21
static bool recordIssuer_
Record issuer name.
Definition: request.h:255
Method methodFromString(std::string method) const
Converts HTTP method specified in textual format to Method.
Definition: request.cc:236
Method
HTTP methods.
Definition: request.h:61
HttpRequestContextPtr context_
Pointer to the HttpRequestContext holding parsed data.
Definition: request.h:288
std::string toBriefString() const
Returns HTTP method, URI and HTTP version as a string.
Definition: request.cc:169
virtual void finalize()
Completes creation of the HTTP request.
Definition: request.cc:132
static bool recordSubject_
Access control parameters: Flags which indicate what information to record.
Definition: request.h:252
Method getMethod() const
Returns HTTP method of the request.
Definition: request.cc:151
virtual void create()
Commits information held in the context into the request.
Definition: request.cc:68
std::string getBody() const
Returns HTTP message body as string.
Definition: request.cc:163
bool isPersistent() const
Checks if the client has requested persistent connection.
Definition: request.cc:214
void requireHttpMethod(const HttpRequest::Method &method)
Specifies an HTTP method allowed for the request.
Definition: request.cc:63
static bool recordBasicAuth_
Record basic auth.
Definition: request.h:258
HttpRequest()
Constructor for inbound HTTP request.
Definition: request.cc:30
std::string getUri() const
Returns HTTP request URI.
Definition: request.cc:157
std::set< Method > required_methods_
Set of required HTTP methods.
Definition: request.h:281
const HttpRequestContextPtr & context() const
Returns pointer to the HttpRequestContext.
Definition: request.h:98
std::string methodToString(const HttpRequest::Method &method) const
Converts HTTP method to string.
Definition: request.cc:258
Method method_
HTTP method of the request.
Definition: request.h:284
virtual void reset()
Reset the state of the object.
Definition: request.cc:143
virtual std::string toString() const
Returns HTTP message as string.
Definition: request.cc:179
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< BasicHttpAuth > BasicHttpAuthPtr
Type of pointers to basic HTTP authentication objects.
Definition: basic_auth.h:70
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-lfc.
Represents basic HTTP authentication header.
Definition: basic_auth.h:73
HTTP header context.
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