@mug-lab/cookie-auth-proxy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +642 -0
- package/SECURITY.md +9 -0
- package/config.json +43 -0
- package/cookie-auth-proxy.config.example.json +43 -0
- package/overrides/README.md +4 -0
- package/package.json +35 -0
- package/src/admin/admin.css +508 -0
- package/src/admin/editors.js +600 -0
- package/src/admin/events.js +325 -0
- package/src/admin/files.js +113 -0
- package/src/admin/renderers.js +513 -0
- package/src/admin/state.js +325 -0
- package/src/admin.html +178 -0
- package/src/config/index.js +372 -0
- package/src/cookie-auth-proxy.schema.json +233 -0
- package/src/diagnostics.js +154 -0
- package/src/init.js +201 -0
- package/src/logger.js +18 -0
- package/src/proxy.js +158 -0
- package/src/regex.js +101 -0
- package/src/runtime/index.js +671 -0
- package/src/sensitive.js +107 -0
- package/src/server/admin-server.js +562 -0
- package/src/server/proxy-server.js +671 -0
- package/src/server/rewrite.js +228 -0
- package/stubs/README.md +8 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const path = require("node:path");
|
|
3
|
+
const { URL } = require("node:url");
|
|
4
|
+
const { compileSafeRegex } = require("../regex");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ローカルプロキシのデフォルト設定。
|
|
8
|
+
* buildConfig()で設定ファイル、環境変数、CLI引数をこの値へ上書きマージする。
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULTS = {
|
|
11
|
+
listenHost: "localhost",
|
|
12
|
+
listenPort: 4300,
|
|
13
|
+
clientOrigin: "http://localhost:8080",
|
|
14
|
+
apiOrigin: "",
|
|
15
|
+
apiOriginAllowedPatterns: [],
|
|
16
|
+
apiPathPatterns: ["^/api(?:/|$)"],
|
|
17
|
+
apiPathExcludes: [
|
|
18
|
+
"^/$",
|
|
19
|
+
"^/favicon\\.ico$",
|
|
20
|
+
"^/(?:assets|static)(?:/|$)",
|
|
21
|
+
"^/sockjs-node(?:/|$)",
|
|
22
|
+
],
|
|
23
|
+
preserveLocationHeaderPatterns: [],
|
|
24
|
+
locationHeaderQueryOverrides: [],
|
|
25
|
+
apiCookie: "",
|
|
26
|
+
sensitiveHeaderNames: [
|
|
27
|
+
"authorization",
|
|
28
|
+
"cookie",
|
|
29
|
+
"proxy-authorization",
|
|
30
|
+
"set-cookie",
|
|
31
|
+
"x-api-key",
|
|
32
|
+
"x-auth-token",
|
|
33
|
+
],
|
|
34
|
+
sensitiveCookieNames: [],
|
|
35
|
+
adminNotice: "",
|
|
36
|
+
startupStubImportDir: "cookie-auth-proxy/stubs",
|
|
37
|
+
startupOverrideImportDir: "cookie-auth-proxy/overrides",
|
|
38
|
+
serverAppPath: "/",
|
|
39
|
+
adminHost: "localhost",
|
|
40
|
+
adminPort: 4301,
|
|
41
|
+
historyLimit: 200,
|
|
42
|
+
maxAdminBodyBytes: 1024 * 1024,
|
|
43
|
+
maxRequestBodyInspectionBytes: 10 * 1024 * 1024,
|
|
44
|
+
maxResponseBodyRewriteBytes: 50 * 1024 * 1024,
|
|
45
|
+
maxHistoryBodyBytes: 512 * 1024,
|
|
46
|
+
allowRemoteAccess: false,
|
|
47
|
+
stubsEnabled: false,
|
|
48
|
+
stubs: [],
|
|
49
|
+
jsonOverridesEnabled: false,
|
|
50
|
+
jsonOverrides: [],
|
|
51
|
+
requestTimeoutMs: 120000,
|
|
52
|
+
logLevel: "info",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* CLI引数、環境変数、設定ファイルからプロキシ設定を作り、
|
|
57
|
+
* 実行時に使うURLオブジェクトと正規表現matcherも事前生成する。
|
|
58
|
+
*
|
|
59
|
+
* @param {string[]} argv node本体とscript pathを除いたCLI引数。
|
|
60
|
+
* @returns {object} マージ済みかつ実行準備済みの設定。
|
|
61
|
+
*/
|
|
62
|
+
function buildConfig(argv) {
|
|
63
|
+
const args = parseArgs(argv);
|
|
64
|
+
const fileConfig = readConfig(args.config);
|
|
65
|
+
const config = mergeConfig(DEFAULTS, fileConfig, readEnv(), args);
|
|
66
|
+
validateLocalOnlyHosts(config);
|
|
67
|
+
|
|
68
|
+
config.apiOriginAllowedMatchers = compilePatterns(
|
|
69
|
+
config.apiOriginAllowedPatterns,
|
|
70
|
+
"apiOriginAllowedPatterns",
|
|
71
|
+
);
|
|
72
|
+
setClientOrigin(config, config.clientOrigin);
|
|
73
|
+
setApiOrigin(config, config.apiOrigin);
|
|
74
|
+
config.publicOriginUrl = new URL(
|
|
75
|
+
`http://${config.listenHost}:${config.listenPort}`,
|
|
76
|
+
);
|
|
77
|
+
config.matchers = {
|
|
78
|
+
apiIncludes: compilePatterns(config.apiPathPatterns, "apiPathPatterns"),
|
|
79
|
+
apiExcludes: compilePatterns(config.apiPathExcludes, "apiPathExcludes"),
|
|
80
|
+
preserveLocation: compilePatterns(
|
|
81
|
+
config.preserveLocationHeaderPatterns,
|
|
82
|
+
"preserveLocationHeaderPatterns",
|
|
83
|
+
),
|
|
84
|
+
};
|
|
85
|
+
config.locationHeaderQueryOverrideRules = compileLocationHeaderQueryOverrides(
|
|
86
|
+
config.locationHeaderQueryOverrides,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
return config;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* CLI引数をキー付きオプションと位置引数へ分解する。
|
|
94
|
+
*/
|
|
95
|
+
function parseArgs(argv) {
|
|
96
|
+
const args = { _: [] };
|
|
97
|
+
|
|
98
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
99
|
+
const raw = argv[i];
|
|
100
|
+
if (!raw.startsWith("--")) {
|
|
101
|
+
args._.push(raw);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const eq = raw.indexOf("=");
|
|
106
|
+
const key = raw.slice(2, eq === -1 ? undefined : eq);
|
|
107
|
+
const next = argv[i + 1];
|
|
108
|
+
const value =
|
|
109
|
+
eq === -1
|
|
110
|
+
? next && !next.startsWith("--")
|
|
111
|
+
? next
|
|
112
|
+
: true
|
|
113
|
+
: raw.slice(eq + 1);
|
|
114
|
+
|
|
115
|
+
if (eq === -1 && next && !next.startsWith("--")) i += 1;
|
|
116
|
+
args[key] = value;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return args;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 指定された設定ファイルを読み込む。
|
|
124
|
+
*/
|
|
125
|
+
function readConfig(configPath) {
|
|
126
|
+
if (!configPath) return {};
|
|
127
|
+
|
|
128
|
+
const absolutePath = path.resolve(process.cwd(), configPath);
|
|
129
|
+
return readJsonFile(absolutePath);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* BOMを除去してJSONファイルを読み込む。
|
|
134
|
+
*/
|
|
135
|
+
function readJsonFile(filePath) {
|
|
136
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8").replace(/^\uFEFF/, ""));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 環境変数からプロキシ設定に対応する値を読み取る。
|
|
141
|
+
*/
|
|
142
|
+
function readEnv() {
|
|
143
|
+
return {
|
|
144
|
+
listenHost: process.env.PROXY_HOST,
|
|
145
|
+
listenPort: process.env.PROXY_PORT && Number(process.env.PROXY_PORT),
|
|
146
|
+
clientOrigin: process.env.CLIENT_ORIGIN,
|
|
147
|
+
apiOrigin: process.env.API_ORIGIN,
|
|
148
|
+
runtimeApiCookie: process.env.API_COOKIE,
|
|
149
|
+
startupStubImportDir: process.env.STARTUP_STUB_IMPORT_DIR,
|
|
150
|
+
startupOverrideImportDir: process.env.STARTUP_OVERRIDE_IMPORT_DIR,
|
|
151
|
+
serverAppPath: process.env.SERVER_APP_PATH,
|
|
152
|
+
adminHost: process.env.ADMIN_HOST,
|
|
153
|
+
adminPort: process.env.ADMIN_PORT && Number(process.env.ADMIN_PORT),
|
|
154
|
+
allowRemoteAccess: parseBoolean(process.env.ALLOW_REMOTE_ACCESS),
|
|
155
|
+
logLevel: process.env.LOG_LEVEL,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* undefinedと空文字の設定値を取り除いたオブジェクトを返す。
|
|
161
|
+
*/
|
|
162
|
+
function compact(value) {
|
|
163
|
+
return Object.fromEntries(
|
|
164
|
+
Object.entries(value).filter(
|
|
165
|
+
([, entry]) => entry !== undefined && entry !== "",
|
|
166
|
+
),
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* デフォルト、設定ファイル、環境変数、CLI引数を優先順にマージする。
|
|
172
|
+
*/
|
|
173
|
+
function mergeConfig(defaults, fileConfig, envConfig, args) {
|
|
174
|
+
const positionalApiOrigin = args._[0];
|
|
175
|
+
const cliConfig = compact({
|
|
176
|
+
listenHost: args.host,
|
|
177
|
+
listenPort: args.port && Number(args.port),
|
|
178
|
+
clientOrigin: args.client,
|
|
179
|
+
apiOrigin: args.api || positionalApiOrigin,
|
|
180
|
+
runtimeApiCookie: args.cookie,
|
|
181
|
+
startupStubImportDir: args["startup-stub-import-dir"],
|
|
182
|
+
startupOverrideImportDir: args["startup-override-import-dir"],
|
|
183
|
+
serverAppPath: args["server-app-path"],
|
|
184
|
+
adminHost: args["admin-host"],
|
|
185
|
+
adminPort: args["admin-port"] && Number(args["admin-port"]),
|
|
186
|
+
allowRemoteAccess: parseBoolean(args["allow-remote-access"]),
|
|
187
|
+
logLevel: args.logLevel,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
...defaults,
|
|
192
|
+
...compact(fileConfig),
|
|
193
|
+
...compact(envConfig),
|
|
194
|
+
...cliConfig,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* 真偽値として扱う設定値をbooleanへ変換する。
|
|
200
|
+
*/
|
|
201
|
+
function parseBoolean(value) {
|
|
202
|
+
if (value === undefined || value === "") return undefined;
|
|
203
|
+
if (value === true || value === false) return value;
|
|
204
|
+
|
|
205
|
+
const normalized = String(value).trim().toLowerCase();
|
|
206
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
207
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
208
|
+
return Boolean(value);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 明示許可なしで管理画面やプロキシをLAN公開しないようにする。
|
|
213
|
+
*/
|
|
214
|
+
function validateLocalOnlyHosts(config) {
|
|
215
|
+
if (config.allowRemoteAccess) return;
|
|
216
|
+
|
|
217
|
+
[
|
|
218
|
+
["listenHost", config.listenHost],
|
|
219
|
+
["adminHost", config.adminHost],
|
|
220
|
+
].forEach(([name, host]) => {
|
|
221
|
+
if (!isLoopbackHost(host)) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
`${name} must be localhost, 127.0.0.1, or ::1 unless --allow-remote-access is specified.`,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* localhostまたはループバックアドレスか判定する。
|
|
231
|
+
*/
|
|
232
|
+
function isLoopbackHost(host) {
|
|
233
|
+
const value = String(host || "").trim().toLowerCase();
|
|
234
|
+
return value === "localhost" || value === "127.0.0.1" || value === "::1";
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Client OriginをOriginだけのURLへ正規化して設定へ反映する。
|
|
239
|
+
*
|
|
240
|
+
* @param {object} config マージ済みプロキシ設定。
|
|
241
|
+
* @param {string} clientOrigin 設定ファイル、CLI、管理画面から入力されたOrigin。
|
|
242
|
+
*/
|
|
243
|
+
function setClientOrigin(config, clientOrigin) {
|
|
244
|
+
const clientOriginUrl = asOrigin(clientOrigin, "clientOrigin");
|
|
245
|
+
config.clientOrigin = clientOriginUrl.origin;
|
|
246
|
+
config.clientOriginUrl = clientOriginUrl;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* API OriginをoriginだけのURLへ正規化し、ホワイトリスト検証後に設定へ反映する。
|
|
251
|
+
*
|
|
252
|
+
* @param {object} config マージ済みプロキシ設定。
|
|
253
|
+
* @param {string} apiOrigin 設定ファイル、CLI、管理画面から入力されたOrigin。
|
|
254
|
+
*/
|
|
255
|
+
function setApiOrigin(config, apiOrigin) {
|
|
256
|
+
if (!apiOrigin) {
|
|
257
|
+
config.apiOrigin = "";
|
|
258
|
+
config.apiOriginUrl = null;
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const apiOriginUrl = asOrigin(apiOrigin, "apiOrigin");
|
|
263
|
+
const allowedMatchers = config.apiOriginAllowedMatchers || [];
|
|
264
|
+
if (
|
|
265
|
+
allowedMatchers.length > 0 &&
|
|
266
|
+
!allowedMatchers.some((pattern) => pattern.test(apiOriginUrl.origin))
|
|
267
|
+
) {
|
|
268
|
+
const error = new Error(
|
|
269
|
+
`API origin is not allowed: ${apiOriginUrl.origin}`,
|
|
270
|
+
);
|
|
271
|
+
error.statusCode = 400;
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
config.apiOrigin = apiOriginUrl.origin;
|
|
276
|
+
config.apiOriginUrl = apiOriginUrl;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* 管理画面またはCLIから指定されたAPI Cookieを実行時設定へ反映する。
|
|
281
|
+
*/
|
|
282
|
+
function setApiCookie(config, apiCookie) {
|
|
283
|
+
config.apiCookie = apiCookie || "";
|
|
284
|
+
config.runtimeApiCookie = apiCookie || "";
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* 現在APIへ注入するCookie文字列を取得する。
|
|
289
|
+
*/
|
|
290
|
+
function getActiveApiCookie(config) {
|
|
291
|
+
return config.runtimeApiCookie || config.apiCookie || "";
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* 入力URLをoriginだけのURLへ正規化する。
|
|
296
|
+
*/
|
|
297
|
+
function asOrigin(value, name) {
|
|
298
|
+
if (!value) {
|
|
299
|
+
throw new Error(`${name} is required.`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const url = new URL(value);
|
|
303
|
+
url.pathname = "";
|
|
304
|
+
url.search = "";
|
|
305
|
+
url.hash = "";
|
|
306
|
+
return url;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* 正規表現文字列の配列をRegExp配列へ変換する。
|
|
311
|
+
*/
|
|
312
|
+
function compilePatterns(patterns, label) {
|
|
313
|
+
if (!Array.isArray(patterns)) {
|
|
314
|
+
throw new Error(`${label} must be an array of regular expression strings.`);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return patterns.map((pattern, index) =>
|
|
318
|
+
compileSafeRegex(pattern, `${label}[${index}]`),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Locationヘッダ内URLのクエリパラメータ書き換えルールを検証し、正規表現を事前コンパイルする。
|
|
324
|
+
*/
|
|
325
|
+
function compileLocationHeaderQueryOverrides(rules) {
|
|
326
|
+
if (!Array.isArray(rules)) {
|
|
327
|
+
throw new Error("locationHeaderQueryOverrides must be an array.");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return rules.map((rule, index) => {
|
|
331
|
+
if (!rule || typeof rule !== "object") {
|
|
332
|
+
throw new Error(
|
|
333
|
+
`locationHeaderQueryOverrides[${index}] must be an object.`,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (!rule.pathPattern) {
|
|
338
|
+
throw new Error(
|
|
339
|
+
`locationHeaderQueryOverrides[${index}].pathPattern is required.`,
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (!rule.queryParams || typeof rule.queryParams !== "object") {
|
|
344
|
+
throw new Error(
|
|
345
|
+
`locationHeaderQueryOverrides[${index}].queryParams is required.`,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
...rule,
|
|
351
|
+
pathMatcher: compileSafeRegex(
|
|
352
|
+
rule.pathPattern,
|
|
353
|
+
`locationHeaderQueryOverrides[${index}].pathPattern`,
|
|
354
|
+
),
|
|
355
|
+
locationMatcher: rule.locationPattern
|
|
356
|
+
? compileSafeRegex(
|
|
357
|
+
rule.locationPattern,
|
|
358
|
+
`locationHeaderQueryOverrides[${index}].locationPattern`,
|
|
359
|
+
)
|
|
360
|
+
: null,
|
|
361
|
+
queryParams: { ...rule.queryParams },
|
|
362
|
+
};
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
module.exports = {
|
|
367
|
+
buildConfig,
|
|
368
|
+
getActiveApiCookie,
|
|
369
|
+
setApiCookie,
|
|
370
|
+
setApiOrigin,
|
|
371
|
+
setClientOrigin,
|
|
372
|
+
};
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Cookie Auth Proxy config",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"additionalProperties": true,
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"listenHost": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"default": "localhost"
|
|
13
|
+
},
|
|
14
|
+
"listenPort": {
|
|
15
|
+
"type": "integer",
|
|
16
|
+
"minimum": 1,
|
|
17
|
+
"maximum": 65535,
|
|
18
|
+
"default": 4300
|
|
19
|
+
},
|
|
20
|
+
"clientOrigin": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"format": "uri",
|
|
23
|
+
"default": "http://localhost:8080"
|
|
24
|
+
},
|
|
25
|
+
"apiOrigin": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"default": ""
|
|
28
|
+
},
|
|
29
|
+
"apiOriginAllowedPatterns": {
|
|
30
|
+
"type": "array",
|
|
31
|
+
"items": {
|
|
32
|
+
"type": "string"
|
|
33
|
+
},
|
|
34
|
+
"default": []
|
|
35
|
+
},
|
|
36
|
+
"apiPathPatterns": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": {
|
|
39
|
+
"type": "string"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"apiPathExcludes": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"items": {
|
|
45
|
+
"type": "string"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"preserveLocationHeaderPatterns": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": {
|
|
51
|
+
"type": "string"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"locationHeaderQueryOverrides": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": {
|
|
57
|
+
"type": "object"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"apiCookie": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"default": ""
|
|
63
|
+
},
|
|
64
|
+
"sensitiveHeaderNames": {
|
|
65
|
+
"type": "array",
|
|
66
|
+
"items": {
|
|
67
|
+
"type": "string"
|
|
68
|
+
},
|
|
69
|
+
"default": [
|
|
70
|
+
"authorization",
|
|
71
|
+
"cookie",
|
|
72
|
+
"proxy-authorization",
|
|
73
|
+
"set-cookie",
|
|
74
|
+
"x-api-key",
|
|
75
|
+
"x-auth-token"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"sensitiveCookieNames": {
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": {
|
|
81
|
+
"type": "string"
|
|
82
|
+
},
|
|
83
|
+
"default": []
|
|
84
|
+
},
|
|
85
|
+
"adminNotice": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"default": ""
|
|
88
|
+
},
|
|
89
|
+
"startupStubImportDir": {
|
|
90
|
+
"type": "string"
|
|
91
|
+
},
|
|
92
|
+
"startupOverrideImportDir": {
|
|
93
|
+
"type": "string"
|
|
94
|
+
},
|
|
95
|
+
"serverAppPath": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"default": "/"
|
|
98
|
+
},
|
|
99
|
+
"adminHost": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"default": "localhost"
|
|
102
|
+
},
|
|
103
|
+
"adminPort": {
|
|
104
|
+
"type": "integer",
|
|
105
|
+
"minimum": 1,
|
|
106
|
+
"maximum": 65535,
|
|
107
|
+
"default": 4301
|
|
108
|
+
},
|
|
109
|
+
"historyLimit": {
|
|
110
|
+
"type": "integer",
|
|
111
|
+
"minimum": 0,
|
|
112
|
+
"default": 200
|
|
113
|
+
},
|
|
114
|
+
"maxAdminBodyBytes": {
|
|
115
|
+
"type": "integer",
|
|
116
|
+
"minimum": 1
|
|
117
|
+
},
|
|
118
|
+
"maxRequestBodyInspectionBytes": {
|
|
119
|
+
"type": "integer",
|
|
120
|
+
"minimum": 0
|
|
121
|
+
},
|
|
122
|
+
"maxResponseBodyRewriteBytes": {
|
|
123
|
+
"type": "integer",
|
|
124
|
+
"minimum": 0
|
|
125
|
+
},
|
|
126
|
+
"maxHistoryBodyBytes": {
|
|
127
|
+
"type": "integer",
|
|
128
|
+
"minimum": 0
|
|
129
|
+
},
|
|
130
|
+
"allowRemoteAccess": {
|
|
131
|
+
"type": "boolean",
|
|
132
|
+
"default": false
|
|
133
|
+
},
|
|
134
|
+
"stubsEnabled": {
|
|
135
|
+
"type": "boolean",
|
|
136
|
+
"default": false
|
|
137
|
+
},
|
|
138
|
+
"stubs": {
|
|
139
|
+
"type": "array",
|
|
140
|
+
"items": {
|
|
141
|
+
"$ref": "#/definitions/stub"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"jsonOverridesEnabled": {
|
|
145
|
+
"type": "boolean",
|
|
146
|
+
"default": false
|
|
147
|
+
},
|
|
148
|
+
"jsonOverrides": {
|
|
149
|
+
"type": "array",
|
|
150
|
+
"items": {
|
|
151
|
+
"$ref": "#/definitions/jsonOverride"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"requestTimeoutMs": {
|
|
155
|
+
"type": "integer",
|
|
156
|
+
"minimum": 1
|
|
157
|
+
},
|
|
158
|
+
"logLevel": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"enum": ["silent", "error", "info", "debug"],
|
|
161
|
+
"default": "info"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"definitions": {
|
|
165
|
+
"ruleCriteria": {
|
|
166
|
+
"type": "object",
|
|
167
|
+
"properties": {
|
|
168
|
+
"name": {
|
|
169
|
+
"type": "string"
|
|
170
|
+
},
|
|
171
|
+
"enabled": {
|
|
172
|
+
"type": "boolean"
|
|
173
|
+
},
|
|
174
|
+
"method": {
|
|
175
|
+
"type": "string",
|
|
176
|
+
"enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "*"]
|
|
177
|
+
},
|
|
178
|
+
"pathPattern": {
|
|
179
|
+
"type": "string"
|
|
180
|
+
},
|
|
181
|
+
"queryParams": {
|
|
182
|
+
"type": "object"
|
|
183
|
+
},
|
|
184
|
+
"requestBody": {
|
|
185
|
+
"type": "object"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"stub": {
|
|
190
|
+
"allOf": [
|
|
191
|
+
{
|
|
192
|
+
"$ref": "#/definitions/ruleCriteria"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"type": "object",
|
|
196
|
+
"properties": {
|
|
197
|
+
"status": {
|
|
198
|
+
"type": "integer",
|
|
199
|
+
"minimum": 100,
|
|
200
|
+
"maximum": 599
|
|
201
|
+
},
|
|
202
|
+
"headers": {
|
|
203
|
+
"type": "object"
|
|
204
|
+
},
|
|
205
|
+
"bodyEncoding": {
|
|
206
|
+
"type": "string",
|
|
207
|
+
"enum": ["json", "text", "base64"]
|
|
208
|
+
},
|
|
209
|
+
"body": {},
|
|
210
|
+
"bodyBase64": {
|
|
211
|
+
"type": "string"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
},
|
|
217
|
+
"jsonOverride": {
|
|
218
|
+
"allOf": [
|
|
219
|
+
{
|
|
220
|
+
"$ref": "#/definitions/ruleCriteria"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"type": "object",
|
|
224
|
+
"properties": {
|
|
225
|
+
"value": {
|
|
226
|
+
"type": "object"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|