Parcourir la source

[5088] Improved HttpResponse and derived classes.

Marcin Siodelski il y a 8 ans
Parent
commit
cbd89c137e
3 fichiers modifiés avec 111 ajouts et 17 suppressions
  1. 16 3
      src/lib/http/response.cc
  2. 7 13
      src/lib/http/response.h
  3. 88 1
      src/lib/http/tests/response_unittests.cc

+ 16 - 3
src/lib/http/response.cc

@@ -5,6 +5,7 @@
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 #include <http/response.h>
+#include <ctime>
 #include <sstream>
 
 using namespace isc::http;
@@ -52,13 +53,13 @@ HttpResponse::setBody(const std::string& body) {
 bool
 HttpResponse::isClientError(const HttpStatusCode& status_code) {
     uint16_t c = statusCodeToNumber(status_code);
-    return ((c >= 400) && (c <= 500));
+    return ((c >= 400) && (c < 500));
 }
 
 bool
 HttpResponse::isServerError(const HttpStatusCode& status_code) {
     uint16_t c = statusCodeToNumber(status_code);
-    return ((c >= 500) && (c <= 600));
+    return ((c >= 500) && (c < 600));
 }
 
 std::string
@@ -78,6 +79,16 @@ HttpResponse::statusCodeToNumber(const HttpStatusCode& status_code) {
 }
 
 std::string
+HttpResponse::getDateHeaderValue() const {
+    time_t rawtime;
+  struct tm * timeinfo;
+
+  time ( &rawtime );
+  timeinfo = localtime ( &rawtime );
+  return (std::string(asctime(timeinfo)));
+}
+
+std::string
 HttpResponse::toString() const {
     std::ostringstream s;
     s << "HTTP/" << http_version_.first << "." << http_version_.second;
@@ -89,8 +100,10 @@ HttpResponse::toString() const {
         s << header->first << ": " << header->second << crlf;
     }
 
+    s << "Date: " << getDateHeaderValue() << crlf;
+
     if (!body_.empty()) {
-        s << "Content-Length" << ": " << body_.length() << crlf;
+        s << "Content-Length: " << body_.length() << crlf;
     }
 
     s << crlf;

+ 7 - 13
src/lib/http/response.h

@@ -57,22 +57,12 @@ public:
 
     HttpResponse(const HttpVersion& version, const HttpStatusCode& status_code);
 
-    virtual ~HttpResponse() {
-    }
-
-    template<typename ValueType>
-    void addHeader(const std::string& name, const ValueType& value) {
-        try {
-            headers_[name] = boost::lexical_cast<std::string>(value);
+    virtual ~HttpResponse() { }
 
-        } catch (const boost::bad_lexical_cast& ex) {
-            isc_throw(HttpResponseError, "unable to convert header value"
-                      " to a string: " << ex.what());
-        }
+    void addHeader(const std::string& name, const std::string& value) {
+        headers_[name] = value;
     }
 
-    void setGenericBody(const HttpStatusCode& status_code) { };
-
     virtual void setBody(const std::string& body);
 
     static bool isClientError(const HttpStatusCode& status_code);
@@ -85,10 +75,14 @@ public:
 
 protected:
 
+    virtual std::string getDateHeaderValue() const;
+
     static uint16_t statusCodeToNumber(const HttpStatusCode& status_code);
 
 private:
 
+    void setGenericBody(const HttpStatusCode& status_code) { };
+
     HttpVersion http_version_;
 
     HttpStatusCode status_code_;

+ 88 - 1
src/lib/http/tests/response_unittests.cc

@@ -9,12 +9,42 @@
 #include <http/response.h>
 #include <gtest/gtest.h>
 #include <sstream>
+#include <string>
 
 using namespace isc::http;
 
 namespace {
 
-TEST(HttpResponseTest, construction) {
+class TestHttpResponse : public HttpResponse {
+public:
+
+    TestHttpResponse(const HttpVersion& version, const HttpStatusCode& status_code)
+        : HttpResponse(version, status_code) {
+    }
+
+    virtual std::string getDateHeaderValue() const {
+        return ("Mon Dec 19 18:53:35 2016");
+    }
+};
+
+class HttpResponseTest : public ::testing::Test {
+public:
+
+    void testResponse(const HttpStatusCode& status_code,
+                      const std::string& status_message) {
+        HttpResponse response(HttpVersion(1, 0), status_code);
+        response.addHeader("Content-Type", "text/html");
+        std::ostringstream response_string;
+        response_string << "HTTP/1.0 " << static_cast<uint16_t>(status_code)
+            << " " << status_message << "\r\n"
+            << "Content-Type: text/html\r\n\r\n";
+
+        EXPECT_EQ(response_string.str(), response.toString());
+    }
+
+};
+
+TEST_F(HttpResponseTest, responseOK) {
     const std::string sample_body =
         "<html>"
         "<head><title>Kea page title</title></head>"
@@ -36,4 +66,61 @@ TEST(HttpResponseTest, construction) {
     EXPECT_EQ(response_string.str(), response.toString());
 }
 
+TEST_F(HttpResponseTest, genericResponse) {
+    testResponse(HttpStatusCode::OK, "OK");
+    testResponse(HttpStatusCode::CREATED, "Created");
+    testResponse(HttpStatusCode::ACCEPTED, "Accepted");
+    testResponse(HttpStatusCode::NO_CONTENT, "No Content");
+    testResponse(HttpStatusCode::MULTIPLE_CHOICES, "Multiple Choices");
+    testResponse(HttpStatusCode::MOVED_PERMANENTLY, "Moved Permanently");
+    testResponse(HttpStatusCode::MOVED_TEMPORARILY, "Moved Temporarily");
+    testResponse(HttpStatusCode::NOT_MODIFIED, "Not Modified");
+    testResponse(HttpStatusCode::BAD_REQUEST, "Bad Request");
+    testResponse(HttpStatusCode::UNAUTHORIZED, "Unauthorized");
+    testResponse(HttpStatusCode::FORBIDDEN, "Forbidden");
+    testResponse(HttpStatusCode::NOT_FOUND, "Not Found");
+    testResponse(HttpStatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error");
+    testResponse(HttpStatusCode::NOT_IMPLEMENTED, "Not Implemented");
+    testResponse(HttpStatusCode::BAD_GATEWAY, "Bad Gateway");
+    testResponse(HttpStatusCode::SERVICE_UNAVAILABLE, "Service Unavailable");
+}
+
+TEST_F(HttpResponseTest, isClientError) {
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::OK));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::CREATED));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::ACCEPTED));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::NO_CONTENT));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::MULTIPLE_CHOICES));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::MOVED_PERMANENTLY));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::MOVED_TEMPORARILY));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::NOT_MODIFIED));
+    EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::BAD_REQUEST));
+    EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::UNAUTHORIZED));
+    EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::FORBIDDEN));
+    EXPECT_TRUE(HttpResponse::isClientError(HttpStatusCode::NOT_FOUND));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::INTERNAL_SERVER_ERROR));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::NOT_IMPLEMENTED));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::BAD_GATEWAY));
+    EXPECT_FALSE(HttpResponse::isClientError(HttpStatusCode::SERVICE_UNAVAILABLE));
+}
+
+TEST_F(HttpResponseTest, isServerError) {
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::OK));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::CREATED));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::ACCEPTED));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::NO_CONTENT));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::MULTIPLE_CHOICES));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::MOVED_PERMANENTLY));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::MOVED_TEMPORARILY));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::NOT_MODIFIED));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::BAD_REQUEST));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::UNAUTHORIZED));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::FORBIDDEN));
+    EXPECT_FALSE(HttpResponse::isServerError(HttpStatusCode::NOT_FOUND));
+    EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::INTERNAL_SERVER_ERROR));
+    EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::NOT_IMPLEMENTED));
+    EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::BAD_GATEWAY));
+    EXPECT_TRUE(HttpResponse::isServerError(HttpStatusCode::SERVICE_UNAVAILABLE));
+}
+
 }