]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#360,!305] Always include Host header in the HTTP requests.
authorMarcin Siodelski <marcin@isc.org>
Tue, 16 Apr 2019 16:33:50 +0000 (18:33 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Mon, 29 Apr 2019 13:37:12 +0000 (15:37 +0200)
src/lib/http/http_header.h
src/lib/http/request.cc
src/lib/http/request.h
src/lib/http/tests/request_unittests.cc

index 975ad35efe33f49717707df67970db09cd949ad8..35d4c17db576a80953ebbfe918381607bc56d574 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -64,6 +64,22 @@ private:
 /// @brief Pointer to the @c HttpHeader class.
 typedef boost::shared_ptr<HttpHeader> HttpHeaderPtr;
 
+/// @brief Represents HTTP Host header.
+class HostHttpHeader : public HttpHeader {
+public:
+
+    /// @brief Constructor.
+    ///
+    /// @param header_value Host header value. The default is empty
+    /// string.
+    explicit HostHttpHeader(const std::string& header_value = "")
+        : HttpHeader("Host", header_value) {
+    }
+};
+
+/// @brief Pointer to the HTTP host header.
+typedef boost::shared_ptr<HostHttpHeader> HostHttpHeaderPtr;
+
 } // end of namespace isc::http
 } // end of namespace isc
 
index d782795f1baf9884b0f4d52bffa84d998e7d9f8e..a6e846e25014e02e3488aa29ba6cbf698cfa5ece 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -27,8 +27,10 @@ HttpRequest::HttpRequest()
       context_(new HttpRequestContext()) {
 }
 
-HttpRequest::HttpRequest(const Method& method, const std::string& uri,
-                         const HttpVersion& version)
+HttpRequest::HttpRequest(const Method& method,
+                         const std::string& uri,
+                         const HttpVersion& version,
+                         const HostHttpHeader& host_header)
     : HttpMessage(OUTBOUND), required_methods_(),
       method_(Method::HTTP_METHOD_UNKNOWN),
       context_(new HttpRequestContext()) {
@@ -36,6 +38,11 @@ HttpRequest::HttpRequest(const Method& method, const std::string& uri,
     context()->uri_ = uri;
     context()->http_version_major_ = version.major_;
     context()->http_version_minor_ = version.minor_;
+    // The Host header is mandatory in HTTP/1.1 and should be placed before
+    // any other headers. We also include it for HTTP/1.0 as it doesn't
+    // harm to include it.
+    context()->headers_.push_back(HttpHeaderContext(host_header.getName(),
+                                                    host_header.getValue()));
 }
 
 void
index 945483d443c7527245e80c6d3e6dc4b2ae03f6cc..dc06600a53449aff75b4776b43db57375dc30040 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -65,10 +65,16 @@ public:
 
     /// @brief Constructor for outbound HTTP request.
     ///
+    /// The constructor always includes Host header in the request, regardless
+    /// of the HTTP version used.
+    ///
     /// @param method HTTP method, e.g. POST.
     /// @param uri URI.
     /// @param version HTTP version.
-    HttpRequest(const Method& method, const std::string& uri, const HttpVersion& version);
+    /// @param host_header Host header to be included in the request. The default
+    /// is the empty Host header.
+    HttpRequest(const Method& method, const std::string& uri, const HttpVersion& version,
+                const HostHttpHeader& host_header = HostHttpHeader());
 
     /// @brief Returns pointer to the @ref HttpRequestContext.
     ///
index 6e0dc598b73139cfd4bef06e4b132cb955f7db65..60f1f6398e785b776923df253b9b4f14fae0c66f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -80,6 +80,47 @@ TEST_F(HttpRequestTest, minimal) {
                  HttpMessageNonExistingHeader);
 }
 
+// This test verifies that empty Host header is included in the
+// request if it is not explicitly specified.
+TEST_F(HttpRequestTest, hostHeaderDefault) {
+    HttpRequestPtr request;
+    ASSERT_NO_THROW(request.reset(new HttpRequest(HttpRequest::Method::HTTP_GET,
+                                                  "/isc/org",
+                                                  HttpVersion(1, 0))));
+
+    ASSERT_NO_THROW(request->finalize());
+
+    EXPECT_EQ(HttpRequest::Method::HTTP_GET, request->getMethod());
+    EXPECT_EQ("/isc/org", request->getUri());
+    EXPECT_EQ(1, request->getHttpVersion().major_);
+    EXPECT_EQ(0, request->getHttpVersion().minor_);
+
+    std::string host_hdr;
+    ASSERT_NO_THROW(host_hdr = request->getHeaderValue("Host"));
+    EXPECT_TRUE(host_hdr.empty());
+}
+
+// This test verifies that it is possible to explicitly specify a
+// Host header value while creating a request.
+TEST_F(HttpRequestTest, hostHeaderCustom) {
+    HttpRequestPtr request;
+    ASSERT_NO_THROW(request.reset(new HttpRequest(HttpRequest::Method::HTTP_GET,
+                                                  "/isc/org",
+                                                  HttpVersion(1, 1),
+                                                  HostHttpHeader("www.example.org"))));
+
+    ASSERT_NO_THROW(request->finalize());
+
+    EXPECT_EQ(HttpRequest::Method::HTTP_GET, request->getMethod());
+    EXPECT_EQ("/isc/org", request->getUri());
+    EXPECT_EQ(1, request->getHttpVersion().major_);
+    EXPECT_EQ(1, request->getHttpVersion().minor_);
+
+    std::string host_hdr;
+    ASSERT_NO_THROW(host_hdr = request->getHeaderValue("Host"));
+    EXPECT_EQ("www.example.org", host_hdr);
+}
+
 TEST_F(HttpRequestTest, includeHeaders) {
     setContextBasics("POST", "/isc/org", HttpVersion(1, 0));
     addHeaderToContext("Content-Length", "1024");