|
@@ -25,6 +25,7 @@ public:
|
|
|
isc::Exception(file, line, what) { };
|
|
|
};
|
|
|
|
|
|
+/// @brief HTTP status codes.
|
|
|
enum class HttpStatusCode : std::uint16_t {
|
|
|
OK = 200,
|
|
|
CREATED = 201,
|
|
@@ -44,6 +45,34 @@ enum class HttpStatusCode : std::uint16_t {
|
|
|
SERVICE_UNAVAILABLE = 503
|
|
|
};
|
|
|
|
|
|
+/// @brief Encapsulates the boolean value indicating if the @ref HttpResponse
|
|
|
+/// constructor should call its @c setGenericBody method during construction.
|
|
|
+struct CallSetGenericBody {
|
|
|
+
|
|
|
+ /// @brief Contrsuctor.
|
|
|
+ ///
|
|
|
+ /// @param set A boolean value indicating if the method should be called
|
|
|
+ /// or not.
|
|
|
+ explicit CallSetGenericBody(const bool set)
|
|
|
+ : set_(set) {
|
|
|
+ }
|
|
|
+
|
|
|
+ /// @brief Returns encapsulated true.
|
|
|
+ static const CallSetGenericBody& yes() {
|
|
|
+ static CallSetGenericBody yes(true);
|
|
|
+ return (yes);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// @brief Returns encapsulated false.
|
|
|
+ static const CallSetGenericBody& no() {
|
|
|
+ static CallSetGenericBody no(false);
|
|
|
+ return (no);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// @brief A storage for the boolean flag.
|
|
|
+ bool set_;
|
|
|
+};
|
|
|
+
|
|
|
class HttpResponse;
|
|
|
|
|
|
/// @brief Pointer to the @ref HttpResponse object.
|
|
@@ -52,43 +81,153 @@ typedef boost::shared_ptr<HttpResponse> HttpResponsePtr;
|
|
|
/// @brief Pointer to the const @ref HttpResponse object.
|
|
|
typedef boost::shared_ptr<const HttpResponse> ConstHttpResponsePtr;
|
|
|
|
|
|
+/// @brief Represents HTTP response message.
|
|
|
+///
|
|
|
+/// This class represents HTTP response message. An instance of this object
|
|
|
+/// or its derivation is typically created by the implementation of the
|
|
|
+/// @ref HttpResponseCreator interface.
|
|
|
+///
|
|
|
+/// It contains @c toString method generating a textual representation of
|
|
|
+/// the HTTP response, which is send to the client over TCP socket.
|
|
|
class HttpResponse {
|
|
|
public:
|
|
|
|
|
|
- HttpResponse(const HttpVersion& version, const HttpStatusCode& status_code);
|
|
|
-
|
|
|
+ /// @brief Constructor.
|
|
|
+ ///
|
|
|
+ /// Creates basic instance of the object. It sets the HTTP version and the
|
|
|
+ /// status code to be included in the response.
|
|
|
+ ///
|
|
|
+ /// @param version HTTP version.
|
|
|
+ /// @param status_code HTTP status code.
|
|
|
+ /// @param generic_body Indicates if the constructor should call
|
|
|
+ /// @c setGenericBody to create a generic content for the given
|
|
|
+ /// status code. This should be set to "no" when the constructor is
|
|
|
+ /// called by the derived class which provides its own implementation
|
|
|
+ /// of the @c setGenericBody method.
|
|
|
+ explicit HttpResponse(const HttpVersion& version,
|
|
|
+ const HttpStatusCode& status_code,
|
|
|
+ const CallSetGenericBody& generic_body =
|
|
|
+ CallSetGenericBody::yes());
|
|
|
+
|
|
|
+ /// @brief Destructor.
|
|
|
+ ///
|
|
|
+ /// A class having virtual methods must have a virtual destructor.
|
|
|
virtual ~HttpResponse() { }
|
|
|
|
|
|
- void addHeader(const std::string& name, const std::string& value) {
|
|
|
- headers_[name] = value;
|
|
|
+ /// @brief Adds HTTP header to the response.
|
|
|
+ ///
|
|
|
+ /// The "Content-Length" and "Date" headers should not be added using this
|
|
|
+ /// method because they are generated and added automatically when the
|
|
|
+ /// @c toString is called.
|
|
|
+ ///
|
|
|
+ /// @param name Header name.
|
|
|
+ /// @param value Header value.
|
|
|
+ /// @tparam ValueType Type of the header value.
|
|
|
+ template<typename ValueType>
|
|
|
+ void addHeader(const std::string& name, const ValueType& value) {
|
|
|
+ addHeaderInternal(name, value, headers_);
|
|
|
}
|
|
|
|
|
|
- virtual void setBody(const std::string& body);
|
|
|
+ /// @brief Assigns body/content to the message.
|
|
|
+ ///
|
|
|
+ /// @param body Body to be assigned.
|
|
|
+ void setBody(const std::string& body);
|
|
|
|
|
|
+ /// @brief Checks if the status code indicates client error.
|
|
|
+ ///
|
|
|
+ /// @param status_code HTTP status code.
|
|
|
+ /// @return true if the status code indicates client error.
|
|
|
static bool isClientError(const HttpStatusCode& status_code);
|
|
|
|
|
|
+ /// @brief Checks if the status code indicates server error.
|
|
|
+ ///
|
|
|
+ /// @param status_code HTTP status code.
|
|
|
+ /// @return true if the status code indicates server error.
|
|
|
static bool isServerError(const HttpStatusCode& status_code);
|
|
|
|
|
|
+ /// @brief Converts status code to string.
|
|
|
+ ///
|
|
|
+ /// @param status_code HTTP status code.
|
|
|
+ /// @return Textual representation of the status code.
|
|
|
static std::string statusCodeToString(const HttpStatusCode& status_code);
|
|
|
|
|
|
- std::string toString() const;
|
|
|
+ /// @brief Returns textual representation of the HTTP response.
|
|
|
+ ///
|
|
|
+ /// It includes the "Date" header with the current time in RFC 1123 format.
|
|
|
+ /// It also includes "Content-Length" when the response has a non-empty
|
|
|
+ /// body.
|
|
|
+ ///
|
|
|
+ /// @return Textual representation of the HTTP response.
|
|
|
+ std::string toString() const ;
|
|
|
|
|
|
protected:
|
|
|
|
|
|
+ /// @brief Adds HTTP header to the map.
|
|
|
+ ///
|
|
|
+ /// @param name Header name.
|
|
|
+ /// @param value Header value.
|
|
|
+ /// @param [out] headers A map to which header value should be inserted.
|
|
|
+ /// @tparam ValueType Type of the header value.
|
|
|
+ template<typename ValueType>
|
|
|
+ void addHeaderInternal(const std::string& name, const ValueType& value,
|
|
|
+ std::map<std::string, std::string>& headers) const {
|
|
|
+ try {
|
|
|
+ headers[name] = boost::lexical_cast<std::string>(value);
|
|
|
+
|
|
|
+ } catch (const boost::bad_lexical_cast& ex) {
|
|
|
+ isc_throw(HttpResponseError, "unable to convert the "
|
|
|
+ << name << " header value to a string");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// @brief Returns current time formatted as required by RFC 1123.
|
|
|
+ ///
|
|
|
+ /// This method is virtual so as it can be overriden in unit tests
|
|
|
+ /// to return a "predictable" value of time, e.g. constant value.
|
|
|
+ ///
|
|
|
+ /// @return Current time formatted as required by RFC 1123.
|
|
|
virtual std::string getDateHeaderValue() const;
|
|
|
|
|
|
+ /// @brief Convenience method converting status code to numeric value.
|
|
|
+ ///
|
|
|
+ /// @param status_code Status code represented as enum.
|
|
|
+ /// @return Numeric representation of the status code.
|
|
|
static uint16_t statusCodeToNumber(const HttpStatusCode& status_code);
|
|
|
|
|
|
private:
|
|
|
|
|
|
+ /// @brief Sets generic body for the given status code.
|
|
|
+ ///
|
|
|
+ /// Most of the classes derived from @ref HttpResponse will expect
|
|
|
+ /// a certain content type. Depending on the content type used they
|
|
|
+ /// will use different body formats for error messages. For example,
|
|
|
+ /// a response using text/html will use HTML within the response
|
|
|
+ /// body. The application/json will use JSON body etc. There is a
|
|
|
+ /// need to implement class specific way of generating the body
|
|
|
+ /// for error messages. Thus, each derivation of this class is
|
|
|
+ /// required to implement class specific @ref setGenericBody function
|
|
|
+ /// which should be called in the class constructor.
|
|
|
+ ///
|
|
|
+ /// This is also the case for this class, though the implementation
|
|
|
+ /// of @c setGenericBody is currently no-op.
|
|
|
+ ///
|
|
|
+ /// Note that this class can't be declared virtual because it is
|
|
|
+ /// meant to be called from the class constructor.
|
|
|
+ ///
|
|
|
+ /// @param status_code Status code for which the body should be
|
|
|
+ /// generated.
|
|
|
void setGenericBody(const HttpStatusCode& status_code) { };
|
|
|
|
|
|
+ /// @brief Holds HTTP version for the response.
|
|
|
HttpVersion http_version_;
|
|
|
|
|
|
+ /// @brief Holds status code for the response.
|
|
|
HttpStatusCode status_code_;
|
|
|
|
|
|
+ /// @brief Holds HTTP headers for the response.
|
|
|
std::map<std::string, std::string> headers_;
|
|
|
|
|
|
+ /// @brief Holds the body/content.
|
|
|
std::string body_;
|
|
|
|
|
|
};
|