コンテンツにスキップ

プラグポイント

Swagger UI は、その内部ロジックのほとんどをプラグインシステムを通じて公開しています。

カスタム動作を実現するために、コア内部をオーバーライドすることがしばしば有益です。

注:セマンティックバージョニング

Swagger UI の内部 API は、当社の公開契約の一部では**ありません**。つまり、メジャーバージョンの変更なしに変更される可能性があります。

カスタムプラグインが内部コア API をラップ、拡張、オーバーライド、または使用する場合、パッチバージョン間では変更されないため、アプリケーションで使用する Swagger UI の特定のマイナーバージョンを指定することをお勧めします。

例えば、NPM 経由で Swagger UI をインストールしている場合、チルダを使用することでこれを行うことができます。

1
{
2
"dependencies": {
3
"swagger-ui": "~3.11.0"
4
}
5
}

fn.opsFilter

filter オプションを使用すると、タグ名はユーザーが指定した値でフィルタリングされます。この動作をカスタマイズしたい場合は、デフォルトの opsFilter 関数をオーバーライドできます。

例えば、複数のフレーズフィルタを実装できます。

1
const MultiplePhraseFilterPlugin = function() {
2
return {
3
fn: {
4
opsFilter: (taggedOps, phrase) => {
5
const phrases = phrase.split(", ")
6
7
return taggedOps.filter((val, key) => {
8
return phrases.some(item => key.indexOf(item) > -1)
9
})
10
}
11
}
12
}
13
}

ロゴコンポーネント

Standalone Preset を使用している場合、SwaggerUI のロゴはトップバーに表示されます。ロゴはプラグイン API を介して Logo コンポーネントを置き換えることで変更できます。

1
import React from "react";
2
const MyLogoPlugin = {
3
components: {
4
Logo: () => (
5
<img alt="My Logo" height="40" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTM3IiBoZWlnaHQ9IjEzNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCiA8Zz4KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+CiAgPHRleHQgdHJhbnNmb3JtPSJtYXRyaXgoMy40Nzc2OSAwIDAgMy4yNjA2NyAtNjczLjEyOCAtNjkxLjk5MykiIHN0cm9rZT0iIzAwMCIgZm9udC1zdHlsZT0ibm9ybWFsIiBmb250LXdlaWdodD0ibm9ybWFsIiB4bWw6c3BhY2U9InByZXNlcnZlIiB0ZXh0LWFuY2hvcj0ic3RhcnQiIGZvbnQtZmFtaWx5PSInT3BlbiBTYW5zIEV4dHJhQm9sZCciIGZvbnQtc2l6ZT0iMjQiIGlkPSJzdmdfMSIgeT0iMjQxLjIyMTkyIiB4PSIxOTYuOTY5MjEiIHN0cm9rZS13aWR0aD0iMCIgZmlsbD0iIzYyYTAzZiI+TXkgTG9nbzwvdGV4dD4KICA8cGF0aCBpZD0ic3ZnXzIiIGQ9Im0zOTUuNjAyNSw1MS4xODM1OWw1My44Nzc3MSwwbDE2LjY0ODYzLC01MS4xODM1OGwxNi42NDg2NCw1MS4xODM1OGw1My44Nzc3LDBsLTQzLjU4NzksMzEuNjMyODNsMTYuNjQ5NDksNTEuMTgzNThsLTQzLjU4NzkyLC0zMS42MzM2OWwtNDMuNTg3OTEsMzEuNjMzNjlsMTYuNjQ5NDksLTUxLjE4MzU4bC00My41ODc5MiwtMzEuNjMyODN6IiBzdHJva2Utd2lkdGg9IjAiIHN0cm9rZT0iIzAwMCIgZmlsbD0iIzYyYTAzZiIvPgogPC9nPgo8L3N2Zz4="/>
6
)
7
}
8
}

JSON Schema コンポーネント

Swagger には、JSON スキーマコンポーネントと呼ばれるものがあります。これらは、application/x-www-form-urlencoded または multipart/* メディアタイプのリクエストボディのパラメータとコンポーネントの入力レンダリングに使用されます。

Swagger は内部的に、OpenAPI Specification のスキーマ情報から JSON スキーマコンポーネントを見つけるために以下のマッピングを使用します。

各スキーマのタイプ(例:stringarray など)と、定義されていればスキーマのフォーマット(例:「date」、「uuid」など)に対応するコンポーネントマッピングがあります。

フォーマットが定義されている場合

1
`JsonSchema_${type}_${format}`

JsonSchema_${type}_${format} コンポーネントが存在しない場合、またはフォーマットが定義されていない場合のフォールバック

1
`JsonSchema_${type}`

デフォルト

1
`JsonSchema_string`

これにより、カスタム入力コンポーネントを定義したり、既存のコンポーネントをオーバーライドしたりできます。

例:Date-Picker プラグイン

日付値を入力したい場合、react-datepicker を swagger-ui に統合するためのカスタムプラグインを提供できます。必要なのは、フォーマットに合わせて react-datepicker をラップするコンポーネントを作成することだけです。

2つのケースがあります。

  • 1
    type: string
    2
    format: date
    マッピングが成功するための結果名: JsonSchema_string_date
  • 1
    type: string
    2
    format: date-time
    マッピングが成功するための結果名: JsonSchema_string_date-time

これにより、フォーマットが日付の場合に時間入力を削除する2つのコンポーネントとシンプルなロジックが必要になります。

1
import React from "react";
2
import DatePicker from "react-datepicker";
3
import "react-datepicker/dist/react-datepicker.css";
4
5
const JsonSchema_string_date = (props) => {
6
const dateNumber = Date.parse(props.value);
7
const date = dateNumber
8
? new Date(dateNumber)
9
: new Date();
10
11
return (
12
<DatePicker
13
selected={date}
14
onChange={d => props.onChange(d.toISOString().substring(0, 10))}
15
/>
16
);
17
}
18
19
const JsonSchema_string_date_time = (props) => {
20
const dateNumber = Date.parse(props.value);
21
const date = dateNumber
22
? new Date(dateNumber)
23
: new Date();
24
25
return (
26
<DatePicker
27
selected={date}
28
onChange={d => props.onChange(d.toISOString())}
29
showTimeSelect
30
timeFormat="p"
31
dateFormat="Pp"
32
/>
33
);
34
}
35
36
37
export const DateTimeSwaggerPlugin = {
38
components: {
39
JsonSchema_string_date: JsonSchema_string_date,
40
"JsonSchema_string_date-time": JsonSchema_string_date_time
41
}
42
};

リクエストスニペット

SwaggerUI は requestSnippetsEnabled: true オプションで設定して、リクエストスニペットを有効にできます。
リクエストを行った際に生成される一般的な curl の代わりに、よりきめ細かなオプションを提供します。

  • bash 用 curl
  • cmd 用 curl
  • powershell 用 curl

独自のスニペットジェネレーターを提供したい場合があります。これはプラグインAPIを使用することで可能です。
リクエストスニペットジェネレーターは、設定と fn で構成されます。
これは内部リクエストオブジェクトを受け取り、目的のスニペットに変換します。

1
// Add config to Request Snippets Configuration with an unique key like "node_native"
2
const snippetConfig = {
3
requestSnippetsEnabled: true,
4
requestSnippets: {
5
generators: {
6
"node_native": {
7
title: "NodeJs Native",
8
syntax: "javascript"
9
}
10
}
11
}
12
}
13
14
const SnippedGeneratorNodeJsPlugin = {
15
fn: {
16
// use `requestSnippetGenerator_` + key from config (node_native) for generator fn
17
requestSnippetGenerator_node_native: (request) => {
18
const url = new Url(request.get("url"))
19
let isMultipartFormDataRequest = false
20
const headers = request.get("headers")
21
if(headers && headers.size) {
22
request.get("headers").map((val, key) => {
23
isMultipartFormDataRequest = isMultipartFormDataRequest || /^content-type$/i.test(key) && /^multipart\/form-data$/i.test(val)
24
})
25
}
26
const packageStr = url.protocol === "https:" ? "https" : "http"
27
let reqBody = request.get("body")
28
if (request.get("body")) {
29
if (isMultipartFormDataRequest && ["POST", "PUT", "PATCH"].includes(request.get("method"))) {
30
return "throw new Error(\"Currently unsupported content-type: /^multipart\\/form-data$/i\");"
31
} else {
32
if (!Map.isMap(reqBody)) {
33
if (typeof reqBody !== "string") {
34
reqBody = JSON.stringify(reqBody)
35
}
36
} else {
37
reqBody = getStringBodyOfMap(request)
38
}
39
}
40
} else if (!request.get("body") && request.get("method") === "POST") {
41
reqBody = ""
42
}
43
44
const stringBody = "`" + (reqBody || "")
45
.replace(/\\n/g, "\n")
46
.replace(/`/g, "\\`")
47
+ "`"
48
49
return `const http = require("${packageStr}");
50
const options = {
51
"method": "${request.get("method")}",
52
"hostname": "${url.host}",
53
"port": ${url.port || "null"},
54
"path": "${url.pathname}"${headers && headers.size ? `,
55
"headers": {
56
${request.get("headers").map((val, key) => `"${key}": "${val}"`).valueSeq().join(",\n ")}
57
}` : ""}
58
};
59
const req = http.request(options, function (res) {
60
const chunks = [];
61
res.on("data", function (chunk) {
62
chunks.push(chunk);
63
});
64
res.on("end", function () {
65
const body = Buffer.concat(chunks);
66
console.log(body.toString());
67
});
68
});
69
${reqBody ? `\nreq.write(${stringBody});` : ""}
70
req.end();`
71
}
72
}
73
}
74
75
const ui = SwaggerUIBundle({
76
"dom_id": "#swagger-ui",
77
deepLinking: true,
78
presets: [
79
SwaggerUIBundle.presets.apis,
80
SwaggerUIStandalonePreset
81
],
82
plugins: [
83
SwaggerUIBundle.plugins.DownloadUrl,
84
SnippedGeneratorNodeJsPlugin
85
],
86
layout: "StandaloneLayout",
87
validatorUrl: "https://validator.swagger.io/validator",
88
url: "https://petstore.swagger.io/v2/swagger.json",
89
...snippetConfig,
90
})

エラー処理

SwaggerUI には、エラー処理を扱う safe-render プラグインがあり、エラー処理システムに接続して変更することができます。

このプラグインは、エラー境界で保護されるべきコンポーネント名のリストを受け入れます。

その公開 API は次のようになります。

1
{
2
fn: {
3
componentDidCatch,
4
withErrorBoundary: withErrorBoundary(getSystem),
5
},
6
components: {
7
ErrorBoundary,
8
Fallback,
9
},
10
}

safe-render プラグインは、base および standalone SwaggerUI プリセットによって自動的に利用され、すべてのコンポーネントがSwaggerUIに認識された後、常に最後のプラグインとして使用されるべきです。このプラグインは、エラー境界によって保護されるべきコンポーネントのデフォルトリストを定義します。

1
[
2
"App",
3
"BaseLayout",
4
"VersionPragmaFilter",
5
"InfoContainer",
6
"ServersContainer",
7
"SchemesContainer",
8
"AuthorizeBtnContainer",
9
"FilterContainer",
10
"Operations",
11
"OperationContainer",
12
"parameters",
13
"responses",
14
"OperationServers",
15
"Models",
16
"ModelWrapper",
17
"Topbar",
18
"StandaloneLayout",
19
"onlineValidatorBadge"
20
]

以下に示すように、設定オプションを持つ safe-render プラグインを利用することで、追加のコンポーネントを保護することができます。これは、SwaggerUI インテグレータであり、追加のカスタムコンポーネントを持つ多数のプラグインを管理している場合に非常に便利です。

1
const swaggerUI = SwaggerUI({
2
url: "https://petstore.swagger.io/v2/swagger.json",
3
dom_id: '#swagger-ui',
4
plugins: [
5
() => ({
6
components: {
7
MyCustomComponent1: () => 'my custom component',
8
},
9
}),
10
SwaggerUI.plugins.SafeRender({
11
fullOverride: true, // only the component list defined here will apply (not the default list)
12
componentList: [
13
"MyCustomComponent1",
14
],
15
}),
16
],
17
});
componentDidCatch

この静的関数は、コンポーネントがエラーをスローした後に呼び出されます。
2つのパラメータを受け取ります。

  1. error - スローされたエラー。
  2. info - コンポーネントスタックキーを持つオブジェクトで、どのコンポーネントがエラーをスローしたかに関する情報が含まれています。

エラー境界の componentDidCatch ライフサイクルメソッドと全く同じシグネチャを持っていますが、これは静的関数であり、クラスメソッドではありません。

componentDidCatch のデフォルトの実装は、受け取ったエラーを表示するために console.error を使用します。

1
export const componentDidCatch = console.error;

独自のエラー処理ロジック(例:bugsnag)を利用するには、componentDidCatch をオーバーライドする新しい SwaggerUI プラグインを作成します。

{% highlight js linenos %} const BugsnagErrorHandlerPlugin = () => { // bugsnag を初期化する

return { fn: { componentDidCatch = (error, info) => { Bugsnag.notify(error); Bugsnag.notify(info); }, }, }; }; {% endhighlight %}

withErrorBoundary

この関数はHOC(Higher Order Component)です。特定のコンポーネントを ErrorBoundary コンポーネントでラップします。プラグインシステムを介してオーバーライドでき、コンポーネントが ErrorBoundary コンポーネントによってどのようにラップされるかを制御できます。99.9%の状況では、この関数をオーバーライドする必要はありませんが、もしオーバーライドする場合は、まずこの関数のソースコードを読んでください。

フォールバック

エラー境界がエラーをキャッチしたときに表示されるコンポーネントです。プラグインシステムを介してオーバーライドできます。そのデフォルトの実装はごく単純です。

1
import React from "react"
2
import PropTypes from "prop-types"
3
4
const Fallback = ({ name }) => (
5
<div className="fallback">
6
😱 <i>Could not render { name === "t" ? "this component" : name }, see the console.</i>
7
</div>
8
)
9
Fallback.propTypes = {
10
name: PropTypes.string.isRequired,
11
}
12
export default Fallback

あなたのルック&フィールに合わせて自由にオーバーライドしてください。

1
const CustomFallbackPlugin = () => ({
2
components: {
3
Fallback: ({ name } ) => `This is my custom fallback. ${name} failed to render`,
4
},
5
});
6
7
const swaggerUI = SwaggerUI({
8
url: "https://petstore.swagger.io/v2/swagger.json",
9
dom_id: '#swagger-ui',
10
plugins: [
11
CustomFallbackPlugin,
12
]
13
});
エラー境界

これは、React エラー境界を実装するコンポーネントです。componentDidCatchFallback を内部で使用します。99.9%の状況では、このコンポーネントをオーバーライドする必要はありませんが、もしオーバーライドする場合は、まずこのコンポーネントのソースコードを読んでください。

動作の変更

以前の SwaggerUI リリース (v4.3.0 以前) では、ほとんどすべてのコンポーネントが保護されており、エラーがスローされると Fallback コンポーネントが表示されていました。これは SwaggerUI v4.3.0 で変更されます。safe-render プラグインで定義されたコンポーネントのみが保護され、フォールバックが表示されるようになりました。SwaggerUI React コンポーネントツリー内のどこかの小さなコンポーネントがレンダリングに失敗してエラーをスローした場合、そのエラーは最も近いエラー境界までバブルアップし、そのエラー境界が Fallback コンポーネントを表示し、componentDidCatch を呼び出します。

© . This site is unofficial and not affiliated with Swagger.