You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by lh...@apache.org on 2026/06/17 22:51:29 UTC
(pulsar-site) branch main updated (1b0909d1b8f -> 58ff852580e)
This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/pulsar-site.git
from 1b0909d1b8f Add link to OpenAPI docs for scalable topics REST API
new 43a45fbb2e7 Serve OpenAPI 3 REST API docs from /openapi/ with openapi*.json names
new 58ff852580e Add rest_api_spec_dir token for REST API spec file links
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
docs/admin-api-tutorial.md | 2 +-
src/config/pulsarVariables.ts | 20 ++++++++++
src/pages/RestApi/RestApi.tsx | 29 +++++++++++---
src/server/remarkPlugins/swagger/index.ts | 46 +++++++++++++++-------
.../swagger.json => openapi/master/openapi.json} | 0
.../master/openapifunctions.json} | 0
.../master/openapilookup.json} | 0
.../master/openapipackages.json} | 0
.../master/openapisink.json} | 0
.../master/openapisource.json} | 0
.../master/openapitransactions.json} | 0
.../master/v2/openapi.json} | 0
.../master/v2/openapilookup.json} | 0
.../master/v3/openapifunctions.json} | 0
.../master/v3/openapipackages.json} | 0
.../master/v3/openapisink.json} | 0
.../master/v3/openapisource.json} | 0
.../master/v3/openapitransactions.json} | 0
static/swagger/restApiVersions.json | 14 +++----
tools/pytools/bin/rest-apidoc-generator.py | 2 +-
tools/pytools/lib/execute/swagger_generator.py | 13 +++++-
tools/pytools/lib/execute/swagger_sorter.py | 16 ++++++--
22 files changed, 109 insertions(+), 33 deletions(-)
rename static/{swagger/master/swagger.json => openapi/master/openapi.json} (100%)
rename static/{swagger/master/swaggerfunctions.json => openapi/master/openapifunctions.json} (100%)
rename static/{swagger/master/swaggerlookup.json => openapi/master/openapilookup.json} (100%)
rename static/{swagger/master/swaggerpackages.json => openapi/master/openapipackages.json} (100%)
rename static/{swagger/master/swaggersink.json => openapi/master/openapisink.json} (100%)
rename static/{swagger/master/swaggersource.json => openapi/master/openapisource.json} (100%)
rename static/{swagger/master/swaggertransactions.json => openapi/master/openapitransactions.json} (100%)
rename static/{swagger/master/v2/swagger.json => openapi/master/v2/openapi.json} (100%)
rename static/{swagger/master/v2/swaggerlookup.json => openapi/master/v2/openapilookup.json} (100%)
rename static/{swagger/master/v3/swaggerfunctions.json => openapi/master/v3/openapifunctions.json} (100%)
rename static/{swagger/master/v3/swaggerpackages.json => openapi/master/v3/openapipackages.json} (100%)
rename static/{swagger/master/v3/swaggersink.json => openapi/master/v3/openapisink.json} (100%)
rename static/{swagger/master/v3/swaggersource.json => openapi/master/v3/openapisource.json} (100%)
rename static/{swagger/master/v3/swaggertransactions.json => openapi/master/v3/openapitransactions.json} (100%)
(pulsar-site) 01/02: Serve OpenAPI 3 REST API docs from /openapi/ with openapi*.json names
Posted by lh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pulsar-site.git
commit 43a45fbb2e79a9a32151fa76864596627a2c7379
Author: Lari Hotari <lh...@users.noreply.github.com>
AuthorDate: Thu Jun 18 01:50:38 2026 +0300
Serve OpenAPI 3 REST API docs from /openapi/ with openapi*.json names
Pulsar master/5.0.0+ publish OpenAPI 3 REST API specs (commit 1d09d5a),
which are conceptually no longer "swagger". Serve them from a parallel
/openapi/ static tree with openapi*.json file names, leaving pre-5.0
releases on /swagger/ with their Swagger 2.0 swagger*.json files.
- RestApi.tsx: choose /openapi/ vs /swagger/ and the openapi*/swagger*
basename via usesOpenApi3(); initialize Redoc explicitly so the download
button saves pulsar_openapi_spec_<version>.json; drop the empty version
segment so the spec URL no longer contains a double slash
- swagger remark plugin: read openapi*.json from static/openapi for
master/5.0.0+, swagger*.json from static/swagger otherwise
- swagger_generator.py: route Gradle (OpenAPI 3) output to static/openapi
and rename swagger*.json -> openapi*.json; Maven stays on static/swagger
- swagger_sorter.py: sort both trees into one combined restApiVersions.json
- move static/swagger/master/swagger*.json -> static/openapi/master/openapi*.json
---
src/pages/RestApi/RestApi.tsx | 29 +++++++++++---
src/server/remarkPlugins/swagger/index.ts | 46 +++++++++++++++-------
.../swagger.json => openapi/master/openapi.json} | 0
.../master/openapifunctions.json} | 0
.../master/openapilookup.json} | 0
.../master/openapipackages.json} | 0
.../master/openapisink.json} | 0
.../master/openapisource.json} | 0
.../master/openapitransactions.json} | 0
.../master/v2/openapi.json} | 0
.../master/v2/openapilookup.json} | 0
.../master/v3/openapifunctions.json} | 0
.../master/v3/openapipackages.json} | 0
.../master/v3/openapisink.json} | 0
.../master/v3/openapisource.json} | 0
.../master/v3/openapitransactions.json} | 0
static/swagger/restApiVersions.json | 14 +++----
tools/pytools/bin/rest-apidoc-generator.py | 2 +-
tools/pytools/lib/execute/swagger_generator.py | 13 +++++-
tools/pytools/lib/execute/swagger_sorter.py | 16 ++++++--
20 files changed, 88 insertions(+), 32 deletions(-)
diff --git a/src/pages/RestApi/RestApi.tsx b/src/pages/RestApi/RestApi.tsx
index 573049f2684..d297ad946ae 100644
--- a/src/pages/RestApi/RestApi.tsx
+++ b/src/pages/RestApi/RestApi.tsx
@@ -72,14 +72,33 @@ class RestApi extends React.Component {
const wrapper = document.querySelector(".container");
const redoc = document.createElement("redoc");
- redoc.setAttribute(
- "spec-url",
- "/swagger/" + version + "/" + apiversion + "/" + swagger + ".json"
- );
+ const openApi3 = usesOpenApi3(version);
+ // Pulsar 5.0.0+/master publish OpenAPI 3 documents under /openapi/ with
+ // "openapi*.json" file names; pre-5.0 releases keep their Swagger 2.0
+ // documents under /swagger/ with "swagger*.json" file names.
+ const specDir = openApi3 ? "/openapi/" : "/swagger/";
+ const specFile = (openApi3 ? swagger.replace("swagger", "openapi") : swagger) + ".json";
+ // Only insert the REST API version segment (v2/v3) when it is known; the
+ // doc links that omit it resolve to the flat spec file at the version root.
+ const specUrl = apiversion
+ ? specDir + version + "/" + apiversion + "/" + specFile
+ : specDir + version + "/" + specFile;
const redocLink = document.createElement("script");
- if (usesOpenApi3(version)) {
+ if (openApi3) {
+ // The redoc2 standalone auto-init only honors the spec-url attribute and
+ // discards every other option, so initialize Redoc explicitly. This lets
+ // us set downloadFileName: the spec saved by Redoc's download button is
+ // named after the Pulsar version rather than the internal "openapi*.json".
redocLink.setAttribute("src", "/js/redoc2.standalone.min.js");
+ redocLink.onload = () => {
+ (window as any).Redoc.init(
+ specUrl,
+ { downloadFileName: "pulsar_openapi_spec_" + version + ".json" },
+ redoc
+ );
+ };
} else {
+ redoc.setAttribute("spec-url", specUrl);
redoc.setAttribute("lazy-rendering", "true");
redocLink.setAttribute("src", "/js/redoc.min.js");
}
diff --git a/src/server/remarkPlugins/swagger/index.ts b/src/server/remarkPlugins/swagger/index.ts
index c0ff56a3987..e8243a15e39 100644
--- a/src/server/remarkPlugins/swagger/index.ts
+++ b/src/server/remarkPlugins/swagger/index.ts
@@ -12,6 +12,7 @@ type PluginOptions = {
baseDir: string;
restApiBaseUrlMapping: Record<SwaggerApiType, string>;
swaggerDir?: string;
+ openapiDir?: string;
};
// Add new return type for getSwaggerJson
@@ -50,20 +51,34 @@ function findLatestVersion(swaggerDir: string, majorMinor: string): string {
}
}
-function getSwaggerFileName(type: SwaggerApiType = 'default'): string {
+// Pulsar 5.0.0+/master publish OpenAPI 3 documents under static/openapi; earlier
+// releases keep their Swagger 2.0 documents under static/swagger. Mirrors
+// usesOpenApi3() in src/pages/RestApi/RestApi.tsx.
+function usesOpenApi3(majorMinor: string): boolean {
+ if (majorMinor === 'master') {
+ return true;
+ }
+ const major = parseInt(majorMinor.split('.')[0], 10);
+ return !isNaN(major) && major >= 5;
+}
+
+function getSwaggerFileName(type: SwaggerApiType = 'default', openApi3 = false): string {
+ // Pulsar 5.0.0+/master spec files are named openapi*.json; earlier releases
+ // use swagger*.json.
+ const prefix = openApi3 ? 'openapi' : 'swagger';
const fileNames: Record<SwaggerApiType, string> = {
- default: 'swagger.json',
- functions: 'swaggerfunctions.json',
- lookup: 'swaggerlookup.json',
- packages: 'swaggerpackages.json',
- sink: 'swaggersink.json',
- source: 'swaggersource.json',
- transactions: 'swaggertransactions.json'
+ default: `${prefix}.json`,
+ functions: `${prefix}functions.json`,
+ lookup: `${prefix}lookup.json`,
+ packages: `${prefix}packages.json`,
+ sink: `${prefix}sink.json`,
+ source: `${prefix}source.json`,
+ transactions: `${prefix}transactions.json`
};
return fileNames[type];
}
-function createSwaggerCache(swaggerDir: string): {
+function createSwaggerCache(swaggerDir: string, openapiDir: string): {
getSwaggerResult: (docPath: string, type?: SwaggerApiType) => SwaggerResult;
} {
const versionCache: {
@@ -77,17 +92,19 @@ function createSwaggerCache(swaggerDir: string): {
getSwaggerResult: (docPath: string, type: SwaggerApiType = 'default') => {
const versionMatch = docPath.match(/version-(\d+\.\d+\.x)/);
const majorMinor = versionMatch ? versionMatch[1].replace('.x', '') : 'master';
+ const openApi3 = usesOpenApi3(majorMinor);
+ const baseDir = openApi3 ? openapiDir : swaggerDir;
const cache = versionCache[majorMinor]?.jsonCache;
-
+
const cacheKey = `${type}`;
if (cache?.has(cacheKey)) {
return cache.get(cacheKey)!;
}
try {
- const fileName = getSwaggerFileName(type);
- const version = majorMinor === 'master' ? 'master' : versionCache[majorMinor]?.latestVersion || findLatestVersion(swaggerDir, majorMinor);
- const filePath = path.join(swaggerDir, version, fileName);
+ const fileName = getSwaggerFileName(type, openApi3);
+ const version = majorMinor === 'master' ? 'master' : versionCache[majorMinor]?.latestVersion || findLatestVersion(baseDir, majorMinor);
+ const filePath = path.join(baseDir, version, fileName);
const jsonContent = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
const result: SwaggerResult = {
@@ -228,7 +245,8 @@ async function processLinkNode(target: Target, context: Context) {
export default function plugin(options: PluginOptions): Transformer {
const swaggerDir = options.swaggerDir || path.join(options.baseDir, 'static/swagger');
- const cache = createSwaggerCache(swaggerDir);
+ const openapiDir = options.openapiDir || path.join(options.baseDir, 'static/openapi');
+ const cache = createSwaggerCache(swaggerDir, openapiDir);
return async (root, vfile) => {
const {visit} = await import('unist-util-visit');
diff --git a/static/swagger/master/swagger.json b/static/openapi/master/openapi.json
similarity index 100%
rename from static/swagger/master/swagger.json
rename to static/openapi/master/openapi.json
diff --git a/static/swagger/master/swaggerfunctions.json b/static/openapi/master/openapifunctions.json
similarity index 100%
rename from static/swagger/master/swaggerfunctions.json
rename to static/openapi/master/openapifunctions.json
diff --git a/static/swagger/master/swaggerlookup.json b/static/openapi/master/openapilookup.json
similarity index 100%
rename from static/swagger/master/swaggerlookup.json
rename to static/openapi/master/openapilookup.json
diff --git a/static/swagger/master/swaggerpackages.json b/static/openapi/master/openapipackages.json
similarity index 100%
rename from static/swagger/master/swaggerpackages.json
rename to static/openapi/master/openapipackages.json
diff --git a/static/swagger/master/swaggersink.json b/static/openapi/master/openapisink.json
similarity index 100%
rename from static/swagger/master/swaggersink.json
rename to static/openapi/master/openapisink.json
diff --git a/static/swagger/master/swaggersource.json b/static/openapi/master/openapisource.json
similarity index 100%
rename from static/swagger/master/swaggersource.json
rename to static/openapi/master/openapisource.json
diff --git a/static/swagger/master/swaggertransactions.json b/static/openapi/master/openapitransactions.json
similarity index 100%
rename from static/swagger/master/swaggertransactions.json
rename to static/openapi/master/openapitransactions.json
diff --git a/static/swagger/master/v2/swagger.json b/static/openapi/master/v2/openapi.json
similarity index 100%
rename from static/swagger/master/v2/swagger.json
rename to static/openapi/master/v2/openapi.json
diff --git a/static/swagger/master/v2/swaggerlookup.json b/static/openapi/master/v2/openapilookup.json
similarity index 100%
rename from static/swagger/master/v2/swaggerlookup.json
rename to static/openapi/master/v2/openapilookup.json
diff --git a/static/swagger/master/v3/swaggerfunctions.json b/static/openapi/master/v3/openapifunctions.json
similarity index 100%
rename from static/swagger/master/v3/swaggerfunctions.json
rename to static/openapi/master/v3/openapifunctions.json
diff --git a/static/swagger/master/v3/swaggerpackages.json b/static/openapi/master/v3/openapipackages.json
similarity index 100%
rename from static/swagger/master/v3/swaggerpackages.json
rename to static/openapi/master/v3/openapipackages.json
diff --git a/static/swagger/master/v3/swaggersink.json b/static/openapi/master/v3/openapisink.json
similarity index 100%
rename from static/swagger/master/v3/swaggersink.json
rename to static/openapi/master/v3/openapisink.json
diff --git a/static/swagger/master/v3/swaggersource.json b/static/openapi/master/v3/openapisource.json
similarity index 100%
rename from static/swagger/master/v3/swaggersource.json
rename to static/openapi/master/v3/openapisource.json
diff --git a/static/swagger/master/v3/swaggertransactions.json b/static/openapi/master/v3/openapitransactions.json
similarity index 100%
rename from static/swagger/master/v3/swaggertransactions.json
rename to static/openapi/master/v3/openapitransactions.json
diff --git a/static/swagger/restApiVersions.json b/static/swagger/restApiVersions.json
index 32c7673c356..a9617d8cbc6 100644
--- a/static/swagger/restApiVersions.json
+++ b/static/swagger/restApiVersions.json
@@ -1757,18 +1757,18 @@
"master": [
{
"fileName": [
- "swagger",
- "swaggerlookup"
+ "openapi",
+ "openapilookup"
],
"version": "v2"
},
{
"fileName": [
- "swaggerfunctions",
- "swaggerpackages",
- "swaggersink",
- "swaggersource",
- "swaggertransactions"
+ "openapifunctions",
+ "openapipackages",
+ "openapisink",
+ "openapisource",
+ "openapitransactions"
],
"version": "v3"
}
diff --git a/tools/pytools/bin/rest-apidoc-generator.py b/tools/pytools/bin/rest-apidoc-generator.py
index ac26f5f2a02..3c13d9899f5 100755
--- a/tools/pytools/bin/rest-apidoc-generator.py
+++ b/tools/pytools/bin/rest-apidoc-generator.py
@@ -41,5 +41,5 @@ if __name__ == '__main__':
master = Path(args.master_path)
swagger_generator.execute(master, args.version)
- swagger_sorter.execute(site_path() / 'static' / 'swagger')
+ swagger_sorter.execute(site_path() / 'static' / 'swagger', site_path() / 'static' / 'openapi')
diff --git a/tools/pytools/lib/execute/swagger_generator.py b/tools/pytools/lib/execute/swagger_generator.py
index 3ce7282cc03..e5d940c6c71 100644
--- a/tools/pytools/lib/execute/swagger_generator.py
+++ b/tools/pytools/lib/execute/swagger_generator.py
@@ -47,9 +47,18 @@ def execute(master: Path, version: str):
mvn = find_command('mvn', msg="mvn is required")
run(mvn, '-pl', 'pulsar-broker', 'install', '-DskipTests', '-Pswagger', cwd=master)
- os.makedirs(site_path() / 'static' / 'swagger' / version, exist_ok=True)
+ # Gradle checkouts (Pulsar master/5.0.0+) emit OpenAPI 3 documents, which are
+ # published under static/openapi/. Maven checkouts (pre-5.0 releases) keep
+ # their Swagger 2.0 documents under static/swagger/.
+ docs_root = 'openapi' if build == pulsar_build.BuildSystem.gradle else 'swagger'
+ os.makedirs(site_path() / 'static' / docs_root / version, exist_ok=True)
for f in master_swaggers.glob('*.json'):
data = json.loads(f.read_text())
- with (site_path() / 'static' / 'swagger' / version / f'{f.stem}.json').open('w+') as m:
+ # The upstream build always names the files swagger*.json; publish them
+ # as openapi*.json under the OpenAPI 3 tree.
+ stem = f.stem
+ if docs_root == 'openapi' and stem.startswith('swagger'):
+ stem = 'openapi' + stem[len('swagger'):]
+ with (site_path() / 'static' / docs_root / version / f'{stem}.json').open('w+') as m:
json.dump(data, m, indent=4, sort_keys=True)
m.write('\n')
diff --git a/tools/pytools/lib/execute/swagger_sorter.py b/tools/pytools/lib/execute/swagger_sorter.py
index 6779e5e56b8..39253a5b999 100644
--- a/tools/pytools/lib/execute/swagger_sorter.py
+++ b/tools/pytools/lib/execute/swagger_sorter.py
@@ -20,9 +20,7 @@ import os
from pathlib import Path
-def execute(base: Path):
- rest_api_versions = {}
-
+def _sort_tree(base: Path, rest_api_versions: dict):
for f in sorted(base.glob('*/*.json')):
filename = f.stem
pulsar_version = f.parent.name
@@ -46,6 +44,18 @@ def execute(base: Path):
json.dump(data, m, indent=4)
m.write('\n')
+
+# Sort both the Swagger 2.0 tree (pre-5.0 releases) and the OpenAPI 3 tree
+# (Pulsar master/5.0.0+) into per-REST-API-version subdirectories, and write a
+# single combined restApiVersions.json index into the Swagger tree, which is
+# where src/utils/index.js and src/config/pulsarVariables.ts import it from.
+def execute(base: Path, openapi_base: Path = None):
+ rest_api_versions = {}
+
+ _sort_tree(base, rest_api_versions)
+ if openapi_base is not None and openapi_base.exists():
+ _sort_tree(openapi_base, rest_api_versions)
+
with (base / 'restApiVersions.json').open('w+') as m:
json.dump(rest_api_versions, m, indent=4, sort_keys=True)
m.write('\n')
(pulsar-site) 02/02: Add rest_api_spec_dir token for REST API spec file links
Posted by lh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pulsar-site.git
commit 58ff852580eea1de0ed1a6bd1f9f9490f893f2ec
Author: Lari Hotari <lh...@users.noreply.github.com>
AuthorDate: Thu Jun 18 01:50:47 2026 +0300
Add rest_api_spec_dir token for REST API spec file links
Resolve to /openapi/<version>/ for master/5.0.0+ docs and /swagger/<version>/
for earlier docs, so the "REST API JSON files" link in admin-api-tutorial.md
points at the correct static tree per version.
---
docs/admin-api-tutorial.md | 2 +-
src/config/pulsarVariables.ts | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/docs/admin-api-tutorial.md b/docs/admin-api-tutorial.md
index e1f64314014..590267911e5 100644
--- a/docs/admin-api-tutorial.md
+++ b/docs/admin-api-tutorial.md
@@ -37,7 +37,7 @@ If you have enabled authentication, you need to provide an auth configuration to
You can find details for the REST API exposed by Pulsar brokers in the [REST API doc](pathname:///admin-rest-api/?version=@pulsar:rest_api_version@).
-If you want to test REST APIs in postman, you can use the REST API JSON files [here](pathname:///swagger/).
+If you want to test REST APIs in postman, you can use the REST API JSON files [here](pathname://@pulsar:rest_api_spec_dir@).
</TabItem>
<TabItem value="Java">
diff --git a/src/config/pulsarVariables.ts b/src/config/pulsarVariables.ts
index a220e5981f8..a3165a5d145 100644
--- a/src/config/pulsarVariables.ts
+++ b/src/config/pulsarVariables.ts
@@ -141,6 +141,20 @@ export function referenceVersion(version: string): string {
return `${v.major}.${v.minor}.x`;
}
+// Pulsar 5.0.0+/master publish OpenAPI 3 REST API docs under /openapi/; earlier
+// releases keep their Swagger 2.0 docs under /swagger/. Mirrors usesOpenApi3()
+// in src/pages/RestApi/RestApi.tsx and src/server/remarkPlugins/swagger/index.ts.
+export function usesOpenApi3(version: string): boolean {
+ if (version === "master") return true;
+ const v = semver.coerce(version);
+ return v !== null && v.major >= 5;
+}
+
+export function restApiSpecDir(restApiVersion: string): string {
+ const root = usesOpenApi3(restApiVersion) ? "openapi" : "swagger";
+ return `/${root}/${restApiVersion}/`;
+}
+
/**
* Token → replacement value for a given version key.
* `"current"` → next/current docs; any other string is an origin version
@@ -159,6 +173,11 @@ export function referenceVersion(version: string): string {
* docs it resolves to `master` (the in-development API), since the REST API viewer keys
* the in-development spec under `master` rather than a numbered release. Versioned docs
* resolve it to their concrete release, matching `version_number`.
+ *
+ * `rest_api_spec_dir` is the static directory that holds the raw REST API spec JSON
+ * files for the doc's version (e.g. `pathname://@pulsar:rest_api_spec_dir@`). Pulsar
+ * 5.0.0+/master docs resolve to `/openapi/<version>/` (OpenAPI 3); earlier docs resolve
+ * to `/swagger/<version>/` (Swagger 2.0).
*/
export function resolveTokens(versionKey: string, referenceLatest = false): Map<string, string> {
const isCurrent = versionKey === "current";
@@ -192,6 +211,7 @@ export function resolveTokens(versionKey: string, referenceLatest = false): Map<
["javadoc:pulsar-functions", javadocVersionUrl(originVersion, "pulsar-functions")],
["offloader_release_url", offloaderReleaseUrl(resolvedVersion)],
["presto_pulsar_connector_release_url", prestoPulsarReleaseUrl(resolvedVersion)],
+ ["rest_api_spec_dir", restApiSpecDir(restApiVersion)],
["rest_api_version", restApiVersion],
["rpm:client-debuginfo", rpmDistUrl(resolvedVersion, "-debuginfo")],
["rpm:client-devel", rpmDistUrl(resolvedVersion, "-devel")],