]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Recognize Accept: */* when deciding which content type to use for replies. 16520/head
authorMiod Vallat <miod.vallat@powerdns.com>
Mon, 17 Nov 2025 15:01:32 +0000 (16:01 +0100)
committerMiod Vallat <miod.vallat@powerdns.com>
Wed, 26 Nov 2025 07:26:07 +0000 (08:26 +0100)
Signed-off-by: Miod Vallat <miod.vallat@powerdns.com>
pdns/webserver.cc
regression-tests.api/test_Zones.py

index 593ecf56662b2a84681945f05abb86ed0a8d4654..77f8719f047d0bc7fec0036579f3d7de5f29db83 100644 (file)
@@ -250,6 +250,34 @@ static void* WebServerConnectionThreadStart(const WebServer* webServer, const st
   return nullptr;
 }
 
+// Decide which content type to use for the answer, based on the
+// `accept' request header. If this header is missing, we try to
+// reply with the same content type as the request.
+static void setupAllowedContentType(HttpRequest& req)
+{
+  auto header = req.headers.find("accept");
+  if (header != req.headers.end()) {
+    // If Accept: */* then we'll happily serve anything!
+    if (header->second.find("*/*") != std::string::npos) {
+      req.accept_yaml = req.accept_json = req.accept_html = true;
+      return;
+    }
+  }
+  else {
+    header = req.headers.find("content-type");
+  }
+  if (header != req.headers.end()) {
+    // yaml wins over json, json wins over html
+    if (header->second.find("application/x-yaml") != std::string::npos || header->second.find("text/x-yaml") != std::string::npos) {
+      req.accept_yaml = true;
+    } else if (header->second.find("application/json") != std::string::npos) {
+      req.accept_json = true;
+    } else if (header->second.find("text/html") != std::string::npos) {
+      req.accept_html = true;
+    }
+  }
+}
+
 void WebServer::handleRequest(HttpRequest& req, HttpResponse& resp) const
 {
   // set default headers
@@ -268,25 +296,7 @@ void WebServer::handleRequest(HttpRequest& req, HttpResponse& resp) const
     SLOG(g_log<<Logger::Debug<<req.logprefix<<"Handling request \"" << req.url.path << "\"" << endl,
          log->info(Logr::Debug, "Handling request"));
 
-    // Decide which content type to use for the answer, based on the
-    // `accept' request header. If this header is missing, we try to
-    // reply with the same content type as the request.
-    auto header = req.headers.find("accept");
-    if (header == req.headers.end()) {
-      header = req.headers.find("content-type");
-    }
-    if (header != req.headers.end()) {
-      // yaml wins over json, json wins over html
-      if (header->second.find("application/x-yaml") != std::string::npos) {
-        req.accept_yaml = true;
-      } else if (header->second.find("text/x-yaml") != std::string::npos) {
-        req.accept_yaml = true;
-      } else if (header->second.find("application/json") != std::string::npos) {
-        req.accept_json = true;
-      } else if (header->second.find("text/html") != std::string::npos) {
-        req.accept_html = true;
-      }
-    }
+    setupAllowedContentType(req);
 
     YaHTTP::THandlerFunction handler;
     YaHTTP::RoutingResult res = YaHTTP::Router::Route(&req, handler);
index 796eacbe2ae39acf475dc9dfce90bed4b991157d..ee2f182815a464dc40db9227447b6389f939eeed 100644 (file)
@@ -1241,8 +1241,7 @@ $NAME$  1D  IN  SOA ns1.example.org. hostmaster.example.org. (
         name, payload, zone = self.create_zone(nameservers=['ns1.foo.com.', 'ns2.foo.com.'], soa_edit_api='')
         # export it
         r = self.session.get(
-            self.url("/api/v1/servers/localhost/zones/" + name + "/export"),
-            headers={'accept': '*/*'}
+            self.url("/api/v1/servers/localhost/zones/" + name + "/export")
         )
         data = r.text.strip().split("\n")
         expected_data = [name + '\t3600\tIN\tNS\tns1.foo.com.',