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

Jackie-Jiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 00d1c88763d Expose authorization header in Swagger API docs (#18974)
00d1c88763d is described below

commit 00d1c88763d4015b9ce966ad7c13a52abf30f9b2
Author: deepinsight coder <[email protected]>
AuthorDate: Thu Jul 16 15:10:48 2026 -0700

    Expose authorization header in Swagger API docs (#18974)
---
 .../pinot/common/swagger/SwaggerSetupUtils.java    | 44 ++++++++++++----
 .../common/swagger/SwaggerSetupUtilsTest.java      | 61 ++++++++++++++++++++++
 2 files changed, 94 insertions(+), 11 deletions(-)

diff --git 
a/pinot-common/src/main/java/org/apache/pinot/common/swagger/SwaggerSetupUtils.java
 
b/pinot-common/src/main/java/org/apache/pinot/common/swagger/SwaggerSetupUtils.java
index ae97abff6c2..93f3088c0d5 100644
--- 
a/pinot-common/src/main/java/org/apache/pinot/common/swagger/SwaggerSetupUtils.java
+++ 
b/pinot-common/src/main/java/org/apache/pinot/common/swagger/SwaggerSetupUtils.java
@@ -18,12 +18,18 @@
  */
 package org.apache.pinot.common.swagger;
 
+import com.google.common.annotations.VisibleForTesting;
 import io.swagger.jaxrs.config.BeanConfig;
+import io.swagger.models.SecurityRequirement;
+import io.swagger.models.Swagger;
+import io.swagger.models.auth.ApiKeyAuthDefinition;
+import io.swagger.models.auth.In;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.Objects;
 import java.util.Properties;
+import javax.ws.rs.core.HttpHeaders;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.pinot.common.utils.PinotStaticHttpHandler;
 import org.apache.pinot.spi.utils.CommonConstants;
@@ -37,6 +43,24 @@ public class SwaggerSetupUtils {
 
   public static void setupSwagger(String componentType, String 
resourcePackage, boolean useHttps, String basePath,
       HttpServer httpServer) {
+    BeanConfig beanConfig = buildSwaggerConfig(componentType, resourcePackage, 
useHttps, basePath);
+    beanConfig.setScan(true);
+
+    ClassLoader classLoader = SwaggerSetupUtils.class.getClassLoader();
+    CLStaticHttpHandler staticHttpHandler = new 
CLStaticHttpHandler(classLoader, "/api/");
+    // map both /api and /help to swagger docs. /api because it looks nice. 
/help for backward compatibility
+    httpServer.getServerConfiguration().addHttpHandler(staticHttpHandler, 
"/api/", "/help/");
+
+    String swaggerVersion = findSwaggerVersion(classLoader);
+    URL swaggerDistLocation = classLoader.getResource(
+            CommonConstants.CONFIG_OF_SWAGGER_RESOURCES_PATH + swaggerVersion 
+ "/");
+    CLStaticHttpHandler swaggerDist = new PinotStaticHttpHandler(new 
URLClassLoader(new URL[]{swaggerDistLocation}));
+    httpServer.getServerConfiguration().addHttpHandler(swaggerDist, 
"/swaggerui-dist/");
+  }
+
+  @VisibleForTesting
+  static BeanConfig buildSwaggerConfig(String componentType, String 
resourcePackage, boolean useHttps,
+      String basePath) {
     BeanConfig beanConfig = new BeanConfig();
     beanConfig.setTitle(String.format("Pinot %s API", componentType));
     beanConfig.setDescription(String.format("APIs for accessing Pinot %s 
information", componentType));
@@ -50,18 +74,16 @@ public class SwaggerSetupUtils {
     }
     beanConfig.setBasePath(basePath);
     beanConfig.setResourcePackage(resourcePackage);
-    beanConfig.setScan(true);
-
-    ClassLoader classLoader = SwaggerSetupUtils.class.getClassLoader();
-    CLStaticHttpHandler staticHttpHandler = new 
CLStaticHttpHandler(classLoader, "/api/");
-    // map both /api and /help to swagger docs. /api because it looks nice. 
/help for backward compatibility
-    httpServer.getServerConfiguration().addHttpHandler(staticHttpHandler, 
"/api/", "/help/");
+    addAuthorizationHeaderSecurity(beanConfig.getSwagger());
+    return beanConfig;
+  }
 
-    String swaggerVersion = findSwaggerVersion(classLoader);
-    URL swaggerDistLocation = classLoader.getResource(
-            CommonConstants.CONFIG_OF_SWAGGER_RESOURCES_PATH + swaggerVersion 
+ "/");
-    CLStaticHttpHandler swaggerDist = new PinotStaticHttpHandler(new 
URLClassLoader(new URL[]{swaggerDistLocation}));
-    httpServer.getServerConfiguration().addHttpHandler(swaggerDist, 
"/swaggerui-dist/");
+  private static void addAuthorizationHeaderSecurity(Swagger swagger) {
+    ApiKeyAuthDefinition authorizationHeader =
+        new ApiKeyAuthDefinition(HttpHeaders.AUTHORIZATION, In.HEADER);
+    authorizationHeader.setDescription("Pinot authentication token. Use 
\"Basic <token>\" or \"Bearer <token>\".");
+    swagger.securityDefinition(CommonConstants.SWAGGER_AUTHORIZATION_KEY, 
authorizationHeader);
+    swagger.security(new 
SecurityRequirement().requirement(CommonConstants.SWAGGER_AUTHORIZATION_KEY));
   }
 
   private static String findSwaggerVersion(ClassLoader classLoader) {
diff --git 
a/pinot-common/src/test/java/org/apache/pinot/common/swagger/SwaggerSetupUtilsTest.java
 
b/pinot-common/src/test/java/org/apache/pinot/common/swagger/SwaggerSetupUtilsTest.java
new file mode 100644
index 00000000000..e19685f53a8
--- /dev/null
+++ 
b/pinot-common/src/test/java/org/apache/pinot/common/swagger/SwaggerSetupUtilsTest.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.pinot.common.swagger;
+
+import io.swagger.jaxrs.config.BeanConfig;
+import io.swagger.models.SecurityRequirement;
+import io.swagger.models.Swagger;
+import io.swagger.models.auth.ApiKeyAuthDefinition;
+import io.swagger.models.auth.In;
+import io.swagger.models.auth.SecuritySchemeDefinition;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.HttpHeaders;
+import org.apache.pinot.spi.utils.CommonConstants;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class SwaggerSetupUtilsTest {
+  @Test
+  public void 
testBuildSwaggerConfigAddsAuthorizationHeaderSecurityDefinition() {
+    BeanConfig beanConfig =
+        SwaggerSetupUtils.buildSwaggerConfig("Controller", 
"org.apache.pinot.common.swagger", false, "/");
+    beanConfig.setScan(true);
+    Swagger swagger = beanConfig.getSwagger();
+
+    Map<String, SecuritySchemeDefinition> securityDefinitions = 
swagger.getSecurityDefinitions();
+    Assert.assertNotNull(securityDefinitions);
+    Assert.assertFalse(securityDefinitions.isEmpty());
+    SecuritySchemeDefinition securityDefinition = 
securityDefinitions.get(CommonConstants.SWAGGER_AUTHORIZATION_KEY);
+    Assert.assertTrue(securityDefinition instanceof ApiKeyAuthDefinition);
+
+    ApiKeyAuthDefinition apiKeyAuthDefinition = (ApiKeyAuthDefinition) 
securityDefinition;
+    Assert.assertEquals(apiKeyAuthDefinition.getName(), 
HttpHeaders.AUTHORIZATION);
+    Assert.assertEquals(apiKeyAuthDefinition.getIn(), In.HEADER);
+    Assert.assertEquals(apiKeyAuthDefinition.getType(), "apiKey");
+
+    List<SecurityRequirement> securityRequirements = swagger.getSecurity();
+    Assert.assertNotNull(securityRequirements);
+    Assert.assertEquals(securityRequirements.size(), 1);
+    Map<String, List<String>> requirements = 
securityRequirements.get(0).getRequirements();
+    
Assert.assertTrue(requirements.containsKey(CommonConstants.SWAGGER_AUTHORIZATION_KEY));
+    
Assert.assertTrue(requirements.get(CommonConstants.SWAGGER_AUTHORIZATION_KEY).isEmpty());
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to