Kea 2.2.0
response.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/date_time.h>
10#include <http/response.h>
11#include <boost/date_time/local_time/local_time.hpp>
12#include <boost/date_time/time_facet.hpp>
13#include <sstream>
14
15using namespace boost::local_time;
16using namespace isc::http;
17
18namespace {
19
21const std::map<HttpStatusCode, std::string> status_code_to_description = {
22 { HttpStatusCode::OK, "OK" },
23 { HttpStatusCode::CREATED, "Created" },
24 { HttpStatusCode::ACCEPTED, "Accepted" },
25 { HttpStatusCode::NO_CONTENT, "No Content" },
26 { HttpStatusCode::MULTIPLE_CHOICES, "Multiple Choices" },
27 { HttpStatusCode::MOVED_PERMANENTLY, "Moved Permanently" },
28 { HttpStatusCode::MOVED_TEMPORARILY, "Moved Temporarily" },
29 { HttpStatusCode::NOT_MODIFIED, "Not Modified" },
30 { HttpStatusCode::BAD_REQUEST, "Bad Request" },
31 { HttpStatusCode::UNAUTHORIZED, "Unauthorized" },
32 { HttpStatusCode::FORBIDDEN, "Forbidden" },
33 { HttpStatusCode::NOT_FOUND, "Not Found" },
34 { HttpStatusCode::REQUEST_TIMEOUT, "Request Timeout" },
35 { HttpStatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error" },
36 { HttpStatusCode::NOT_IMPLEMENTED, "Not Implemented" },
37 { HttpStatusCode::BAD_GATEWAY, "Bad Gateway" },
38 { HttpStatusCode::SERVICE_UNAVAILABLE, "Service Unavailable" }
39};
40
42const std::string crlf = "\r\n";
43
44}
45
46namespace isc {
47namespace http {
48
50 : HttpMessage(INBOUND), context_(new HttpResponseContext()) {
51}
52
54 const HttpStatusCode& status_code,
55 const CallSetGenericBody& generic_body)
56 : HttpMessage(OUTBOUND), context_(new HttpResponseContext()) {
57 context_->http_version_major_ = version.major_;
58 context_->http_version_minor_ = version.minor_;
59 context_->status_code_ = static_cast<unsigned int>(status_code);
60
61 if (generic_body.set_) {
62 // This currently does nothing, but it is useful to have it here as
63 // an example how to implement it in the derived classes.
64 setGenericBody(status_code);
65 }
66}
67
68void
70 try {
71 http_version_.major_ = context_->http_version_major_;
72 http_version_.minor_ = context_->http_version_minor_;
73
74 // Check if the HTTP version is allowed for this request.
76 isc_throw(BadValue, "use of HTTP version "
77 << http_version_.major_ << "."
79 << " not allowed");
80 }
81
82 // Copy headers from the context.
83 for (auto header = context_->headers_.begin();
84 header != context_->headers_.end();
85 ++header) {
86 HttpHeaderPtr hdr(new HttpHeader(header->name_, header->value_));
87 headers_[hdr->getLowerCaseName()] = hdr;
88 }
89
91 HttpHeaderPtr length_header(new HttpHeader("Content-Length", boost::lexical_cast<std::string>
92 (context_->body_.length())));
93 headers_["content-length"] = length_header;
94
95 HttpHeaderPtr date_header(new HttpHeader("Date", getDateHeaderValue()));;
96 headers_["date"] = date_header;
97 }
98
99 // Iterate over required headers and check that they exist
100 // in the HTTP response.
101 for (auto req_header = required_headers_.begin();
102 req_header != required_headers_.end();
103 ++req_header) {
104 auto header = headers_.find(req_header->first);
105 if (header == headers_.end()) {
106 isc_throw(BadValue, "required header " << req_header->first
107 << " not found in the HTTP response");
108 } else if (!req_header->second->getValue().empty() &&
109 !header->second->isValueEqual(req_header->second->getValue())) {
110 // If specific value is required for the header, check
111 // that the value in the HTTP response matches it.
112 isc_throw(BadValue, "required header's " << header->first
113 << " value is " << req_header->second->getValue()
114 << ", but " << header->second->getValue() << " was found");
115 }
116 }
117
118 } catch (const std::exception& ex) {
119 // Reset the state of the object if we failed at any point.
120 reset();
122 }
123
124 // All ok.
125 created_ = true;
126}
127
128void
130 if (!created_) {
131 create();
132 }
133
134 finalized_ = true;
135}
136
137void
139 created_ = false;
140 finalized_ = false;
141 headers_.clear();
142}
143
146 checkCreated();
147 return (static_cast<HttpStatusCode>(context_->status_code_));
148}
149
150std::string
152 checkCreated();
153 return (context_->phrase_);
154}
155
156std::string
159 return (context_->body_);
160}
161
162bool
164 // Client errors have status codes of 4XX.
165 uint16_t c = statusCodeToNumber(status_code);
166 return ((c >= 400) && (c < 500));
167}
168
169bool
171 // Server errors have status codes of 5XX.
172 uint16_t c = statusCodeToNumber(status_code);
173 return ((c >= 500) && (c < 600));
174}
175
176std::string
178 auto status_code_it = status_code_to_description.find(status_code);
179 if (status_code_it == status_code_to_description.end()) {
180 isc_throw(HttpResponseError, "internal server error: no HTTP status"
181 " description for the given status code "
182 << static_cast<uint16_t>(status_code));
183 }
184 return (status_code_it->second);
185}
186
187uint16_t
189 return (static_cast<uint16_t>(status_code));
190}
191
192std::string
194 // This returns current time in the recommended format.
195 HttpDateTime date_time;
196 return (date_time.rfc1123Format());
197}
198
199std::string
202
203 std::ostringstream s;
204 // HTTP version number and status code.
205 s << "HTTP/" << http_version_.major_ << "." << http_version_.minor_;
206 s << " " << context_->status_code_;
207 s << " " << statusCodeToString(static_cast<HttpStatusCode>(context_->status_code_));
208 return (s.str());
209}
210
211std::string
213
214 std::ostringstream s;
215 // HTTP version number and status code.
216 s << toBriefString() << crlf;
217
218 for (auto header_it = headers_.cbegin(); header_it != headers_.cend();
219 ++header_it) {
220 s << header_it->second->getName() << ": " << header_it->second->getValue()
221 << crlf;
222 }
223
224 s << crlf;
225
226 // Include message body.
227 s << getBody();
228
229 return (s.str());
230}
231
232} // namespace http
233} // namespace isc
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.
This class parses and generates time values used in HTTP.
Definition: date_time.h:41
std::string rfc1123Format() const
Returns time value formatted as specified in RFC 1123.
Definition: date_time.cc:30
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
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
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 HttpResponse class.
Definition: response.h:23
HttpResponseContextPtr context_
Pointer to the HttpResponseContext holding parsed data.
Definition: response.h:235
virtual std::string getBody() const
Returns HTTP response body as string.
Definition: response.cc:157
HttpResponse()
Constructor for the inbound HTTP response.
Definition: response.cc:49
static uint16_t statusCodeToNumber(const HttpStatusCode &status_code)
Convenience method converting status code to numeric value.
Definition: response.cc:188
static bool isClientError(const HttpStatusCode &status_code)
Checks if the status code indicates client error.
Definition: response.cc:163
HttpStatusCode getStatusCode() const
Returns HTTP status code.
Definition: response.cc:145
virtual std::string getDateHeaderValue() const
Returns current time formatted as required by RFC 1123.
Definition: response.cc:193
static bool isServerError(const HttpStatusCode &status_code)
Checks if the status code indicates server error.
Definition: response.cc:170
std::string toBriefString() const
Returns HTTP version and HTTP status as a string.
Definition: response.cc:200
virtual void finalize()
Completes creation of the HTTP response.
Definition: response.cc:129
virtual std::string toString() const
Returns HTTP response as string.
Definition: response.cc:212
std::string getStatusPhrase() const
Returns HTTP status phrase.
Definition: response.cc:151
virtual void reset()
Reset the state of the object.
Definition: response.cc:138
virtual void create()
Commits information held in the context into the response.
Definition: response.cc:69
static std::string statusCodeToString(const HttpStatusCode &status_code)
Converts status code to string.
Definition: response.cc:177
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
HttpStatusCode
HTTP status codes (cf RFC 2068)
Definition: response.h:30
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.
Encapsulates the boolean value indicating if the HttpResponse constructor should call its setGenericB...
Definition: response.h:52
bool set_
A storage for the boolean flag.
Definition: response.h:75
HTTP response context.
HTTP protocol version.
Definition: http_types.h:14
unsigned minor_
Minor HTTP version.
Definition: http_types.h:16
unsigned major_
Major HTTP version.
Definition: http_types.h:15