This is an automated email from the ASF dual-hosted git repository.

alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/master by this push:
     new d2b70fef7 KUDU-3543: Add JSON Content-Type Header
d2b70fef7 is described below

commit d2b70fef79d963099c8def7632521d3f31da81ff
Author: Marton Greber <[email protected]>
AuthorDate: Mon Aug 12 14:46:11 2024 +0000

    KUDU-3543: Add JSON Content-Type Header
    
    This patch introduces path handlers for pages that require the
    Content-Type header application/json and integrates them accordingly.
    Additionally, the test data has been updated to ensure proper coverage.
    
    Change-Id: I37b442cb3e8be68f7b243e66ed5ebe369df07829
    Reviewed-on: http://gerrit.cloudera.org:8080/21661
    Tested-by: Alexey Serbin <[email protected]>
    Reviewed-by: Alexey Serbin <[email protected]>
---
 src/kudu/master/master_path_handlers.cc  |  4 ++--
 src/kudu/server/default_path_handlers.cc |  6 ++----
 src/kudu/server/rpcz-path-handler.cc     |  4 ++--
 src/kudu/server/tracing_path_handlers.cc |  4 ++--
 src/kudu/server/webserver.cc             | 15 +++++++++++++++
 src/kudu/server/webserver.h              |  7 +++++++
 src/kudu/util/jwt-util-test.cc           |  8 ++++----
 src/kudu/util/mini_oidc.cc               |  9 +++------
 src/kudu/util/test_util.cc               | 29 +++++++++++++++--------------
 src/kudu/util/web_callback_registry.h    | 11 ++++++++++-
 10 files changed, 62 insertions(+), 35 deletions(-)

diff --git a/src/kudu/master/master_path_handlers.cc 
b/src/kudu/master/master_path_handlers.cc
index f1c36fdfe..fb6efc484 100644
--- a/src/kudu/master/master_path_handlers.cc
+++ b/src/kudu/master/master_path_handlers.cc
@@ -915,12 +915,12 @@ Status MasterPathHandlers::Register(Webserver* server) {
       [this](const Webserver::WebRequest& req, 
Webserver::PrerenderedWebResponse* resp) {
         this->HandleIpkiCaCert(DataFormat::DER, req, resp);
       });
-  server->RegisterPrerenderedPathHandler(
+  server->RegisterJsonPathHandler(
       "/dump-entities", "Dump Entities",
       [this](const Webserver::WebRequest& req, 
Webserver::PrerenderedWebResponse* resp) {
         this->HandleDumpEntities(req, resp);
       },
-      StyleMode::UNSTYLED, false);
+      false /*is_on_nav_bar*/);
   return Status::OK();
 }
 
diff --git a/src/kudu/server/default_path_handlers.cc 
b/src/kudu/server/default_path_handlers.cc
index 7457710ac..e125d9658 100644
--- a/src/kudu/server/default_path_handlers.cc
+++ b/src/kudu/server/default_path_handlers.cc
@@ -533,13 +533,11 @@ void RegisterMetricsJsonHandler(Webserver* webserver, 
const MetricRegistry* cons
   };
   bool not_on_nav_bar = false;
   bool is_on_nav_bar = true;
-  webserver->RegisterPrerenderedPathHandler("/metrics", "JSON Metrics", 
callback,
-                                            StyleMode::UNSTYLED, 
is_on_nav_bar);
+  webserver->RegisterJsonPathHandler("/metrics", "JSON Metrics", callback, 
is_on_nav_bar);
 
   // The old name -- this is preserved for compatibility with older releases of
   // monitoring software which expects the old name.
-  webserver->RegisterPrerenderedPathHandler("/jsonmetricz", "Metrics", 
callback,
-                                            StyleMode::UNSTYLED, 
not_on_nav_bar);
+  webserver->RegisterJsonPathHandler("/jsonmetricz", "Metrics", callback, 
not_on_nav_bar);
 }
 
 void RegisterMetricsPrometheusHandler(Webserver* webserver, const 
MetricRegistry* const metrics) {
diff --git a/src/kudu/server/rpcz-path-handler.cc 
b/src/kudu/server/rpcz-path-handler.cc
index 159639f9d..53b05daa1 100644
--- a/src/kudu/server/rpcz-path-handler.cc
+++ b/src/kudu/server/rpcz-path-handler.cc
@@ -77,12 +77,12 @@ void RpczPathHandler(const shared_ptr<Messenger>& messenger,
 } // anonymous namespace
 
 void AddRpczPathHandlers(const shared_ptr<Messenger>& messenger, Webserver* 
webserver) {
-  webserver->RegisterPrerenderedPathHandler(
+  webserver->RegisterJsonPathHandler(
       "/rpcz", "RPCs",
       [messenger](const Webserver::WebRequest& req, 
Webserver::PrerenderedWebResponse* resp) {
         RpczPathHandler(messenger, req, resp);
       },
-      StyleMode::UNSTYLED, true /*is_on_nav_bar*/);
+      true /*is_on_nav_bar*/);
 }
 
 } // namespace kudu
diff --git a/src/kudu/server/tracing_path_handlers.cc 
b/src/kudu/server/tracing_path_handlers.cc
index 086424936..fe51f05dd 100644
--- a/src/kudu/server/tracing_path_handlers.cc
+++ b/src/kudu/server/tracing_path_handlers.cc
@@ -273,11 +273,11 @@ void TracingPathHandlers::RegisterHandlers(Webserver* 
server) {
 
   typedef pair<const string, Handler> HandlerPair;
   for (const HandlerPair& e : handlers) {
-    server->RegisterPrerenderedPathHandler(
+    server->RegisterJsonPathHandler(
         e.first, "", [e](const Webserver::WebRequest& req,
                          Webserver::PrerenderedWebResponse* resp) {
           HandleRequest(e.second, req, resp);
-        }, StyleMode::UNSTYLED, false /* is_on_nav_bar */);
+        }, false /* is_on_nav_bar */);
   }
 }
 
diff --git a/src/kudu/server/webserver.cc b/src/kudu/server/webserver.cc
index 0a52227d3..a734259cb 100644
--- a/src/kudu/server/webserver.cc
+++ b/src/kudu/server/webserver.cc
@@ -754,6 +754,9 @@ void Webserver::SendResponse(struct sq_connection* 
connection,
     case StyleMode::BINARY:
       content_type = "application/octet-stream";
       break;
+    case StyleMode::JSON:
+      content_type = "application/json";
+      break;
     default:
       LOG(DFATAL) << "unexpected style mode: " << static_cast<uint32_t>(mode);
       break;
@@ -870,6 +873,18 @@ void Webserver::RegisterBinaryDataPathHandler(
                                                      callback));
 }
 
+void Webserver::RegisterJsonPathHandler(
+    const string& path,
+    const string& alias,
+    const PrerenderedPathHandlerCallback& callback,
+    bool is_on_nav_bar) {
+  std::lock_guard l(lock_);
+  InsertOrDie(&path_handlers_, path, new PathHandler(StyleMode::JSON,
+                                                     is_on_nav_bar,
+                                                     alias,
+                                                     callback));
+}
+
 bool Webserver::MustacheTemplateAvailable(const string& path) const {
   if (!static_pages_available()) {
     return false;
diff --git a/src/kudu/server/webserver.h b/src/kudu/server/webserver.h
index a1be885f0..3de8a8784 100644
--- a/src/kudu/server/webserver.h
+++ b/src/kudu/server/webserver.h
@@ -86,6 +86,13 @@ class Webserver : public WebCallbackRegistry {
       const std::string& alias,
       const PrerenderedPathHandlerCallback& callback) override;
 
+  // Register route 'path' for application/json responses.
+  void RegisterJsonPathHandler(
+      const std::string& path,
+      const std::string& alias,
+      const PrerenderedPathHandlerCallback& callback,
+      bool is_on_nav_bar) override;
+
   // Change the footer HTML to be displayed at the bottom of all styled web 
pages.
   void set_footer_html(const std::string& html);
 
diff --git a/src/kudu/util/jwt-util-test.cc b/src/kudu/util/jwt-util-test.cc
index 0b2d380ec..a6e1cf341 100644
--- a/src/kudu/util/jwt-util-test.cc
+++ b/src/kudu/util/jwt-util-test.cc
@@ -850,8 +850,8 @@ class JWKSMockServer {
     opts.port = 0;
     opts.bind_interface = "127.0.0.1";
     webserver_.reset(new Webserver(opts));
-    webserver_->RegisterPrerenderedPathHandler("/jwks", "JWKS", 
SimpleJWKSHandler,
-                                               StyleMode::UNSTYLED, 
/*is_on_nav_bar*/false);
+    webserver_->RegisterJsonPathHandler("/jwks", "JWKS", SimpleJWKSHandler,
+                                               /*is_on_nav_bar*/false);
     RETURN_NOT_OK(webserver_->Start());
     vector<Sockaddr> addrs;
     RETURN_NOT_OK(webserver_->GetBoundAddresses(&addrs));
@@ -870,13 +870,13 @@ class JWKSMockServer {
     for (const auto& ar : account_id_to_resp) {
       const auto& account_id = ar.first;
       const auto& jwks = ar.second;
-      webserver_->RegisterPrerenderedPathHandler(Substitute("/jwks/$0", 
account_id), account_id,
+      webserver_->RegisterJsonPathHandler(Substitute("/jwks/$0", account_id), 
account_id,
           [account_id, jwks] (const Webserver::WebRequest& /*req*/,
                               Webserver::PrerenderedWebResponse* resp) {
             resp->output << jwks;
             resp->status_code = HttpStatusCode::Ok;
           },
-          StyleMode::UNSTYLED, /*is_on_nav_bar*/false);
+          /*is_on_nav_bar*/false);
     }
     RETURN_NOT_OK(webserver_->Start());
     vector<Sockaddr> addrs;
diff --git a/src/kudu/util/mini_oidc.cc b/src/kudu/util/mini_oidc.cc
index fda284588..3d53a1bb6 100644
--- a/src/kudu/util/mini_oidc.cc
+++ b/src/kudu/util/mini_oidc.cc
@@ -111,7 +111,7 @@ Status MiniOidc::Start() {
 
   // For clients with oidc discovery
   for (const auto& [account_id, valid] : options_.account_ids) {
-    jwks_server_->RegisterPrerenderedPathHandler(
+    jwks_server_->RegisterJsonPathHandler(
         Substitute("/jwks/$0", account_id),
         account_id,
         [account_id = account_id, valid = valid](const Webserver::WebRequest&  
/*req*/,
@@ -126,12 +126,11 @@ Status MiniOidc::Start() {
                                      kRsaInvalidPubKeyJwkN, kRsaPubKeyJwkE),
               resp->status_code = HttpStatusCode::Ok;
         },
-        StyleMode::UNSTYLED,
         /*is_on_nav_bar*/ false);
   }
 
   // for clients without oidc discovery
-  jwks_server_->RegisterPrerenderedPathHandler(
+  jwks_server_->RegisterJsonPathHandler(
       "/jwks.json",
       "jwks",
       [&](const Webserver::WebRequest&  /*req*/, 
Webserver::PrerenderedWebResponse* resp) {
@@ -146,7 +145,6 @@ Status MiniOidc::Start() {
                                    kRsaPubKeyJwkE),
         resp->status_code = HttpStatusCode::Ok;
       },
-      StyleMode::UNSTYLED,
       /*is_on_nav_bar*/ false);
 
   LOG(INFO) << "Starting JWKS server";
@@ -174,7 +172,7 @@ Status MiniOidc::Start() {
   oidc_opts.port = 0;
   oidc_opts.bind_interface = "localhost";
   oidc_server_.reset(new Webserver(oidc_opts));
-  oidc_server_->RegisterPrerenderedPathHandler(
+  oidc_server_->RegisterJsonPathHandler(
       "/.well-known/openid-configuration",
       "openid-configuration",
       // Pass the 'accountId' query arguments to return a response that
@@ -183,7 +181,6 @@ Status MiniOidc::Start() {
                            Webserver::PrerenderedWebResponse* resp) {
         OidcDiscoveryHandler(req, resp, discovery_jwks_url);
       },
-      StyleMode::UNSTYLED,
       /*is_on_nav_bar*/ false);
 
   LOG(INFO) << "Starting OIDC Discovery server";
diff --git a/src/kudu/util/test_util.cc b/src/kudu/util/test_util.cc
index 9129a5ce8..4afc40fc7 100644
--- a/src/kudu/util/test_util.cc
+++ b/src/kudu/util/test_util.cc
@@ -100,6 +100,7 @@ static const uint64_t kTestBeganAtMicros = 
Env::Default()->NowMicros();
 static const char* const kContentTypeTextPlain = "text/plain";
 static const char* const kContentTypeTextHtml = "text/html";
 static const char* const kContentTypeApplicationOctet = 
"application/octet-stream";
+static const char* const kContentTypeApplicationJson = "application/json";
 
 // Global which production code can check to see if it is running
 // in a GTest environment (assuming the test binary links in this module,
@@ -667,10 +668,10 @@ const unordered_map<string, string>& 
GetCommonWebserverEndpoints() {
       {"stacks", kContentTypeTextPlain},
       {"version", kContentTypeTextPlain},
       {"healthz", kContentTypeTextPlain},
-      {"metrics", kContentTypeTextPlain},
-      {"jsonmetricz", kContentTypeTextPlain},
+      {"metrics", kContentTypeApplicationJson},
+      {"jsonmetricz", kContentTypeApplicationJson},
       {"metrics_prometheus", kContentTypeTextPlain},
-      {"rpcz", kContentTypeTextPlain},
+      {"rpcz", kContentTypeApplicationJson},
       {"startup", kContentTypeTextHtml},
       {"pprof/cmdline", kContentTypeTextPlain},
       {"pprof/heap", kContentTypeTextPlain},
@@ -678,16 +679,16 @@ const unordered_map<string, string>& 
GetCommonWebserverEndpoints() {
       {"pprof/profile", kContentTypeTextPlain},
       {"pprof/symbol", kContentTypeTextPlain},
       {"pprof/contention", kContentTypeTextPlain},
-      {"tracing/json/begin_monitoring", kContentTypeTextPlain},
-      {"tracing/json/end_monitoring", kContentTypeTextPlain},
-      {"tracing/json/capture_monitoring", kContentTypeTextPlain},
-      {"tracing/json/get_monitoring_status", kContentTypeTextPlain},
-      {"tracing/json/categories", kContentTypeTextPlain},
-      {"tracing/json/begin_recording", kContentTypeTextPlain},
-      {"tracing/json/get_buffer_percent_full", kContentTypeTextPlain},
-      {"tracing/json/end_recording", kContentTypeTextPlain},
-      {"tracing/json/end_recording_compressed", kContentTypeTextPlain},
-      {"tracing/json/simple_dump", kContentTypeTextPlain}};
+      {"tracing/json/begin_monitoring", kContentTypeApplicationJson},
+      {"tracing/json/end_monitoring", kContentTypeApplicationJson},
+      {"tracing/json/capture_monitoring", kContentTypeApplicationJson},
+      {"tracing/json/get_monitoring_status", kContentTypeApplicationJson},
+      {"tracing/json/categories", kContentTypeApplicationJson},
+      {"tracing/json/begin_recording", kContentTypeApplicationJson},
+      {"tracing/json/get_buffer_percent_full", kContentTypeApplicationJson},
+      {"tracing/json/end_recording", kContentTypeApplicationJson},
+      {"tracing/json/end_recording_compressed", kContentTypeApplicationJson},
+      {"tracing/json/simple_dump", kContentTypeApplicationJson}};
   return common_endpoints;
 }
 
@@ -716,7 +717,7 @@ const unordered_map<string, string>& 
GetMasterWebserverEndpoints(const string& t
       {"ipki-ca-cert", kContentTypeTextPlain},
       {"ipki-ca-cert-pem", kContentTypeTextPlain},
       {"ipki-ca-cert-der", kContentTypeApplicationOctet},
-      {"dump-entities", kContentTypeTextPlain}};
+      {"dump-entities", kContentTypeApplicationJson}};
   return master_endpoints;
 }
 
diff --git a/src/kudu/util/web_callback_registry.h 
b/src/kudu/util/web_callback_registry.h
index d0e39db44..2c405de98 100644
--- a/src/kudu/util/web_callback_registry.h
+++ b/src/kudu/util/web_callback_registry.h
@@ -46,7 +46,9 @@ enum class StyleMode {
   // In this mode, the response is sent without any styling elements.
   UNSTYLED,
   // In rare cases when a binary data is sent as a response.
-  BINARY
+  BINARY,
+  // This mode is used when the server response is in JSON format.
+  JSON
 };
 
 // Interface for registering webserver callbacks.
@@ -146,6 +148,13 @@ class WebCallbackRegistry {
       const std::string& alias,
       const PrerenderedPathHandlerCallback& callback) = 0;
 
+  // Register a callback for a URL path that returns JSON.
+  virtual void RegisterJsonPathHandler(
+      const std::string& path,
+      const std::string& alias,
+      const PrerenderedPathHandlerCallback& callback,
+      bool is_on_nav_bar) = 0;
+
   // Returns true if 'req' was proxied via Knox, false otherwise.
   static bool IsProxiedViaKnox(const WebRequest& req);
 };

Reply via email to