WSDL / SOAP viewer logo

Backstage WSDL / SOAP viewer Plugin

Created by dweber019

Many teams still run SOAP services. WSDL is the XML format that describes those services, their operations, the messages they accept, and how clients should call them. The WSDL and SOAP viewer plugin brings that information into Backstage so engineers can read it without leaving the portal.

The plugin adds a WSDL view to Backstage API Docs. It takes a WSDL file and renders a clear page that shows bindings, ports, types, and example requests. The result is a human readable overview that fits the way Backstage presents other API specs. Behind the scenes it uses a small backend to fetch and process definitions, then applies an XSLT based transformation to format the content for the frontend.

Common use cases are simple. Make SOAP endpoints discoverable in the catalog. Help new engineers understand an old integration. Speed up on call work by keeping operations and types one click away from the owning service. Support migrations by listing what a service exposes today. None of this asks teams to rewrite their specs. It just displays what you already have in WSDL.

If you track APIs as Backstage entities you can mark the type as WSDL and the plugin will render it in place. The project is listed in the Backstage plugin directory and sees regular updates, which helps it stay current with Backstage releases.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

Copy
yarn --cwd packages/app add @dweber019/backstage-plugin-api-docs-module-wsdl

Register the client and widget in packages app

Add the API factory and widget in packages/app/apis.ts

Copy
// packages/app/apis.ts

import { AnyApiFactory, createApiFactory, discoveryApiRef, identityApiRef } from '@backstage/core-plugin-api';
import { apiDocsConfigRef, defaultDefinitionWidgets } from '@backstage/plugin-api-docs';
import { ApiEntity } from '@backstage/catalog-model';

import {
  apiDocsModuleWsdlApiRef,
  ApiDocsModuleWsdlClient,
  wsdlApiWidget,
} from '@dweber019/backstage-plugin-api-docs-module-wsdl';

export const apis: AnyApiFactory[] = [
  createApiFactory({
    api: apiDocsModuleWsdlApiRef,
    deps: {
      identityApi: identityApiRef,
      discoveryApi: discoveryApiRef,
    },
    factory: ({ identityApi, discoveryApi }) =>
      new ApiDocsModuleWsdlClient({ identityApi, discoveryApi }),
  }),
  createApiFactory({
    api: apiDocsConfigRef,
    deps: {},
    factory: () => {
      const definitionWidgets = defaultDefinitionWidgets();
      return {
        getApiDefinitionWidget: (apiEntity: ApiEntity) => {
          if (apiEntity.spec.type.toLowerCase() === 'wsdl') {
            return wsdlApiWidget(apiEntity);
          }
          return definitionWidgets.find(d => d.type === apiEntity.spec.type);
        },
      };
    },
  }),
];

This goes in your existing apis array. The widget renders for API entities with spec.type set to wsdl.

Add a WSDL API entity in your catalog

Point the definition to a WSDL location. Use a URL or a file location supported by your setup.

Copy
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: hello-world
  description: Hello World example for WSDL
spec:
  type: wsdl
  lifecycle: deprecated
  owner: foo
  definition:
    $text: http://www.dneonline.com/calculator.asmx?wsdl

Install the backend package

You must install the backend plugin. The frontend uses a backend endpoint for loading and transforming WSDL.

Copy
yarn --cwd packages/backend add @dweber019/backstage-plugin-api-docs-module-wsdl-backend @backstage/catalog-client

Old backend system setup

Create a router module and mount it under the backend app.

Copy
// packages/backend/src/plugins/apiDocsModuleWsdl.ts

import { Router } from 'express';
import { CatalogClient } from '@backstage/catalog-client';
import { createRouter } from '@dweber019/backstage-plugin-api-docs-module-wsdl-backend';
import { PluginEnvironment } from '../types';

export default async function createPlugin(env: PluginEnvironment): Promise<Router> {
  const catalogClient = new CatalogClient({ discoveryApi: env.discovery });

  return await createRouter({
    logger: env.logger,
    config: env.config,
    discovery: env.discovery,
    auth: env.auth,
    catalogClient,
  });
}

Mount the router in packages/backend/src/index.ts

Copy
// packages/backend/src/index.ts

import { createEnv, useHotMemoize } from './lib/createEnv';
import apiDocsModuleWsdl from './plugins/apiDocsModuleWsdl';

// inside main bootstrap
const wsdlEnv = useHotMemoize(module, () => createEnv('api-docs-module-wsdl'));
app.use(
  '/api/api-docs-module-wsdl',
  await apiDocsModuleWsdl(wsdlEnv),
);

This exposes the service under the discovery plugin id api-docs-module-wsdl

New backend system setup

Wrap the router in a small backend feature and register it. This mounts the HTTP router during startup.

Create a module in packages/backend

Copy
// packages/backend/src/plugins/apiDocsModuleWsdlPlugin.ts

import { coreServices, createBackendPlugin } from '@backstage/backend-plugin-api';
import { CatalogClient } from '@backstage/catalog-client';
import { createRouter } from '@dweber019/backstage-plugin-api-docs-module-wsdl-backend';

export const apiDocsModuleWsdlPlugin = createBackendPlugin({
  id: 'api-docs-module-wsdl',
  register(env) {
    env.registerInit({
      deps: {
        logger: coreServices.logger,
        httpRouter: coreServices.httpRouter,
        discovery: coreServices.discovery,
        auth: coreServices.auth,
        rootConfig: coreServices.rootConfig,
      },
      async init({ logger, httpRouter, discovery, auth, rootConfig }) {
        const catalogClient = new CatalogClient({ discoveryApi: discovery });

        const router = await createRouter({
          logger,
          config: rootConfig,
          discovery,
          auth,
          catalogClient,
        });

        httpRouter.use(router);
      },
    });
  },
});

Register the feature in your backend entry point

Copy
// packages/backend/src/index.ts

import { createBackend } from '@backstage/backend-defaults';
import { apiDocsModuleWsdlPlugin } from './plugins/apiDocsModuleWsdlPlugin';

const backend = createBackend();

backend.add(apiDocsModuleWsdlPlugin());

backend.start();

Where you will see it in the app

Open the API page for an entity with type wsdl in the API Docs plugin. The widget renders the WSDL view there.

Changelog

This changelog is produced from commits made to the WSDL / SOAP viewer plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.

Maintenance

  • Update Backstage to 1.41.1 for the WSDL module version 0.1.1. Update the WSDL backend version 1.1.1. #108 merged 2 months ago. Release #107 merged 2 months ago.

  • Update Backstage to 1.41.0 for the WSDL module version 0.1.0. Remove React imports. Update the WSDL backend version 1.1.0. #101 merged 3 months ago. Release #102 merged 3 months ago.

  • Update Backstage to 1.36.1 for the WSDL module version 0.0.20. Update the WSDL backend version 1.0.4. #92 merged 6 months ago. Release #93 merged 6 months ago.

  • Update Backstage to 1.35.0 for the WSDL module version 0.0.19. Update the WSDL backend version 1.0.3. #86 merged 8 months ago. Release #87 merged 8 months ago.

  • Update Backstage to 1.34.2 for the WSDL module version 0.0.18. Update the WSDL backend version 1.0.2. #84 merged 9 months ago. Release #85 merged 9 months ago.

  • Update Backstage dependencies to 1.32.2 for the WSDL module version 0.0.17. Update the WSDL backend version 1.0.1. Release #77 merged 11 months ago.

Breaking changes

  • None

Set up Backstage in minutes with Roadie