Kea 2.7.6
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
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();
124 isc_throw(HttpRequestError, ex.what());
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
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...
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.
HttpHeaderMap headers_
Parsed HTTP headers.
HttpVersion http_version_
HTTP version numbers.
HttpVersion getHttpVersion() const
Returns HTTP version number (major and minor).
void checkFinalized() const
Checks if the finalize was called.
void checkCreated() const
Checks if the create was called.
bool created_
Flag indicating whether create was called.
std::set< HttpVersion > required_versions_
Set of required HTTP versions.
Direction getDirection() const
Returns HTTP message direction.
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.
HttpHeaderPtr getHeader(const std::string &header_name) const
Returns object encapsulating HTTP header.
bool finalized_
Flag indicating whether finalize was called.
HttpHeaderMap required_headers_
Map holding required HTTP headers.
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 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