diff --git a/.changeset/purple-chefs-wait.md b/.changeset/purple-chefs-wait.md
new file mode 100644
index 0000000000..d8489e0275
--- /dev/null
+++ b/.changeset/purple-chefs-wait.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-api-docs': minor
+---
+
+Adding requestInterceptor option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI.
diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt
index c61c6bdf46..1706556ce8 100644
--- a/.github/vale/Vocab/Backstage/accept.txt
+++ b/.github/vale/Vocab/Backstage/accept.txt
@@ -296,6 +296,7 @@ readonly
rebase
Recharts
Redash
+requestInterceptor
replicasets
repo
Repo
diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md
index 27e19b218d..f74fc19e92 100644
--- a/plugins/api-docs/README.md
+++ b/plugins/api-docs/README.md
@@ -222,3 +222,42 @@ security:
## Links
- [The Backstage homepage](https://backstage.io)
+
+### Adding requestInterceptor to Swagger UI
+
+To configure a [requestInterceptor for Swagger UI](https://github.com/swagger-api/swagger-ui/tree/master/flavors/swagger-ui-react#requestinterceptor-proptypesfunc) you'll need to add the following to your `api.tsx`:
+
+```tsx
+...
+import { OpenApiDefinitionWidget, apiDocsConfigRef, defaultDefinitionWidgets } from '@backstage/plugin-api-docs';
+import { ApiEntity } from '@backstage/catalog-model';
+
+export const apis: AnyApiFactory[] = [
+...
+createApiFactory({
+ api: apiDocsConfigRef,
+ deps: {},
+ factory: () => {
+ // Overriding openapi definition widget to add cors-anywhere proxy
+ const requestInterceptor = (req: any) => {
+ // Adding cors-anywhere proxy to the request url
+ console.log(req);
+ req.url = "https://cors-anywhere.herokuapp.com/" + req.url;
+ return req;
+ };
+ const definitionWidgets = defaultDefinitionWidgets();
+ definitionWidgets[definitionWidgets.findIndex(obj => obj.type === 'openapi')] = {
+ type: 'openapi',
+ title: 'OpenAPI',
+ rawLanguage: 'yaml',
+ component: (definition) => ,
+ };
+
+ return {
+ getApiDefinitionWidget: (apiEntity: ApiEntity) => {
+ return definitionWidgets.find(d => d.type === apiEntity.spec.type);
+ },
+ };
+ },
+ })
+```
diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md
index a9b21664c3..783e2bdecb 100644
--- a/plugins/api-docs/api-report.md
+++ b/plugins/api-docs/api-report.md
@@ -54,7 +54,7 @@ const apiDocsPlugin: BackstagePlugin<
{
registerApi: ExternalRouteRef;
},
- {}
+ ApiDocsInputPluginOptions
>;
export { apiDocsPlugin };
export { apiDocsPlugin as plugin };
diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx
index 735fba86f7..adbd069908 100644
--- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx
+++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx
@@ -38,8 +38,14 @@ paths:
"200":
description: Success
`;
+
+ const requestInterceptor = (req: any) => req;
+
const { getByText } = await renderInTestApp(
- ,
+ ,
);
// swagger-ui loads the documentation asynchronously
diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx
index 5d5988399a..624f99e4a1 100644
--- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx
+++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx
@@ -18,6 +18,7 @@ import { makeStyles } from '@material-ui/core/styles';
import React, { useEffect, useState } from 'react';
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
+import { Request } from './';
const useStyles = makeStyles(theme => ({
root: {
@@ -136,9 +137,13 @@ const useStyles = makeStyles(theme => ({
export type OpenApiDefinitionProps = {
definition: string;
+ requestInterceptor?: (req: Request) => Request | Promise;
};
-export const OpenApiDefinition = ({ definition }: OpenApiDefinitionProps) => {
+export const OpenApiDefinition = ({
+ definition,
+ requestInterceptor,
+}: OpenApiDefinitionProps) => {
const classes = useStyles();
// Due to a bug in the swagger-ui-react component, the component needs
@@ -152,7 +157,12 @@ export const OpenApiDefinition = ({ definition }: OpenApiDefinitionProps) => {
return (
-
+
);
};
diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx
index 424a52136b..809934ee11 100644
--- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx
+++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx
@@ -16,6 +16,7 @@
import { Progress } from '@backstage/core-components';
import React, { Suspense } from 'react';
+import { Request } from './';
// The swagger-ui component and related CSS has a significant size, only load it
// if the element is actually used.
@@ -28,6 +29,7 @@ const LazyOpenApiDefinition = React.lazy(() =>
/** @public */
export type OpenApiDefinitionWidgetProps = {
definition: string;
+ requestInterceptor?: (req: Request) => Request | Promise;
};
/** @public */
diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts
index e317d42a59..f23f560347 100644
--- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts
+++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts
@@ -16,3 +16,7 @@
export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget';
export type { OpenApiDefinitionWidgetProps } from './OpenApiDefinitionWidget';
+
+export interface Request {
+ [k: string]: any;
+}