From df2cbfa45a7449ebfd8c3c565d3d0f0e42eddc2c Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Thu, 22 Oct 2026 21:26:26 -0400 Subject: [PATCH 1/8] Add a script to browse Solr's v2 API with Swagger UI locally Regenerates the OpenAPI spec, fetches swagger-ui-dist via npm, and drops a same-origin Swagger UI page into a running `./gradlew dev` instance so you can "Try it out" against a real local Solr without writing client code. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01RzzUgiebQ8ZhhgE2E7ZZU5 --- dev-docs/apis.adoc | 2 + dev-docs/local-api-explorer.adoc | 46 ++++++++ dev-tools/scripts/launch-api-explorer.sh | 132 +++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 dev-docs/local-api-explorer.adoc create mode 100755 dev-tools/scripts/launch-api-explorer.sh diff --git a/dev-docs/apis.adoc b/dev-docs/apis.adoc index b394b16d4522..1cd60a4e765b 100644 --- a/dev-docs/apis.adoc +++ b/dev-docs/apis.adoc @@ -47,6 +47,8 @@ Many libraries implement the JAX-RS spec: Solr currently uses the implementation These v2 API definitions consist of two parts: a JAX-RS annotated interface in the `api` module "defining" the API, and a class in `core` "implementing" the interface. Separating the API "definition" and "implementation" in this way allows us to only define each API in a single place, and use code generators to produce other API-related bits such as SolrJ code and ref-guide documentation. +One of those other bits is an OpenAPI spec - see link:local-api-explorer.adoc[local-api-explorer.adoc] for how to browse it with Swagger UI against a running local Solr. + === Writing JAX-RS APIs Writing a new v2 API may appear daunting, but additions in reality are actually pretty simple: diff --git a/dev-docs/local-api-explorer.adoc b/dev-docs/local-api-explorer.adoc new file mode 100644 index 000000000000..4763a712ff9b --- /dev/null +++ b/dev-docs/local-api-explorer.adoc @@ -0,0 +1,46 @@ += Browsing the V2 API with Swagger UI + +Solr's v2 (JAX-RS) API is described by an OpenAPI spec that's generated at build time +from the `@Operation`-annotated interfaces in `solr/api/src/java/.../client/api/endpoint` +(the same spec that feeds the generated JS/Python SolrJ clients). +You can point a local https://swagger.io/tools/swagger-ui/[Swagger UI] instance at that +spec to browse the API and fire live "Try it out" requests against a running Solr, without +writing any client code. + +== Usage + +First, start a local Solr, e.g. via `./gradlew dev` and `bin/solr start -c`. + +Then run: + +[source,bash] +---- +./dev-tools/scripts/launch-api-explorer.sh +---- + +and open `\http://localhost:8983/solr/ui/openapi/index.html`. + +The script regenerates the spec (`./gradlew :solr:api:resolve`), fetches a local copy of +`swagger-ui-dist` via npm, and writes the page alongside Solr's other static Admin UI +resources, under the running instance's `server/solr-webapp/webapp/ui/openapi/` directory. +Re-run the script any time you've rebuilt the server (e.g. after checking out a different +branch) to refresh the spec and pick up any new or changed endpoints. + +If you're pointing at a Solr instance whose webapp lives somewhere other than +`solr/packaging/build/dev/server/solr-webapp/webapp` (the default for `./gradlew dev`), +pass its path as the first argument. + +== Notes + +* The generated files live under a gradle build directory and under the Solr instance's + own server directory - they are not tracked by git and won't survive a `clean` or a + fresh `bin/solr start` against a different instance. +* The page is served from the same origin as the API it's exploring + (`http://localhost:8983/solr/ui/openapi/...` calling `http://localhost:8983/api/...`), + which avoids any CORS setup. It has to be placed under `/ui/*` specifically, since + that's one of the few paths the Admin UI's `web.xml` maps to a static-file servlet - + anywhere else falls through to Solr's own request-handling servlet and 404s. +* Solr sends a `Content-Security-Policy: script-src 'self' ...` header (no + `'unsafe-inline'`) on every response, so the page's Swagger UI init code has to live in + its own same-origin `.js` file rather than an inline ` + + + + +HTML + +# Solr sends `Content-Security-Policy: script-src 'self' ...` with no +# 'unsafe-inline' on every response, so the init call has to live in its own +# same-origin file - an inline + + + + diff --git a/solr/webapp/web/libs/swagger-ui/openapi-init.js b/solr/webapp/web/libs/swagger-ui/openapi-init.js new file mode 100644 index 000000000000..01c20cfff4e4 --- /dev/null +++ b/solr/webapp/web/libs/swagger-ui/openapi-init.js @@ -0,0 +1,11 @@ +// Solr sends a `Content-Security-Policy: script-src 'self' ...` header (no +// 'unsafe-inline') on every response, so this initialization has to live in its own +// same-origin file - an inline - - - - -HTML - -# Solr sends `Content-Security-Policy: script-src 'self' ...` with no -# 'unsafe-inline' on every response, so the init call has to live in its own -# same-origin file - an inline - - +
+ + diff --git a/solr/webapp/web/libs/swagger-ui/openapi-init.js b/solr/webapp/web/libs/scalar/scalar-init.js similarity index 62% rename from solr/webapp/web/libs/swagger-ui/openapi-init.js rename to solr/webapp/web/libs/scalar/scalar-init.js index aa489f27c984..0e00ccff0a3f 100644 --- a/solr/webapp/web/libs/swagger-ui/openapi-init.js +++ b/solr/webapp/web/libs/scalar/scalar-init.js @@ -15,14 +15,13 @@ limitations under the License. */ -// Solr sends a `Content-Security-Policy: script-src 'self' ...` header (no -// 'unsafe-inline') on every response, so this initialization has to live in its own -// same-origin file - an inline + @@ -196,6 +197,8 @@

Connection recovered...

  • Thread Dump

  • +
  • API Explorer

  • +
  • Open New UI

  • @@ -267,7 +270,6 @@

    Connection recovered...