Skip to content

Commit b5ad0ce

Browse files
authored
Fix OpenAPI v2 parsing (#3498)
1 parent 2ba7e54 commit b5ad0ce

File tree

4 files changed

+24
-9
lines changed

4 files changed

+24
-9
lines changed

.changeset/witty-eyes-relax.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@gitbook/openapi-parser": patch
3+
---
4+
5+
Fix OpenAPI v2 parsing

packages/openapi-parser/src/parse.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { OpenAPIParseError } from './error';
33
import { parseOpenAPI } from './parse';
44

55
const spec = await Bun.file(new URL('./fixtures/recursive-spec.json', import.meta.url)).text();
6+
const specV2 = await Bun.file(new URL('./fixtures/spec-v2.json', import.meta.url)).text();
67

78
const html = `<!DOCTYPE html><html lang=\"en\"><head> <meta charset=\"utf-8\"> <title>API Documentation</title> <base href=\"/api-docs/\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> <link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\"> <link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.7.0/css/all.css\" integrity=\"sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ\" crossorigin=\"anonymous\"> <style>@import\"https://fonts.googleapis.com/css2?family=Nunito:wght@200&display=swap\";@charset \"UTF-8\";:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-color-rgb:33,37,41;--bs-body-bg-rgb:255,255,255;--bs-font-sans-serif:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",\"Noto Sans\",\"Liberation Sans\",Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",\"Noto Color Emoji\";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, .175);--bs-border-radius:.375rem;--bs-border-radius-sm:.25rem;--bs-border-radius-lg:.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-2xl:2rem;--bs-border-radius-pill:50rem;--bs-link-color:#0d6efd;--bs-link-hover-color:#0a58ca;--bs-code-color:#d63384;--bs-highlight-bg:#fff3cd}*,:after,:before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}:root{--primaryColor1:#373e3e;--primaryColor2:#373e3e;--white:#ffffff;--lightGrey:#F8F9F9;--grey:#F8F9F9;--darkGrey:#6c757d;--black:black}*{box-sizing:border-box}body{font-family:Nunito,sans-serif;background-color:var(--grey);margin:5px auto}</style><link rel=\"stylesheet\" href=\"styles.css\" media=\"print\" onload=\"this.media='all'\"><noscript><link rel=\"stylesheet\" href=\"styles.css\"></noscript></head> <body> <app-root></app-root> <script> parent.postMessage(location.hash, location.origin); </script> <script src=\"runtime.js\" type=\"module\"></script><script src=\"polyfills.js\" type=\"module\"></script><script src=\"scripts.js\" defer></script><script src=\"main.js\" type=\"module\"></script> <script type=\"text/javascript\" src=\"/_Incapsula_Resource?SWJIYLWA=719d34d31c8e3a6e6fffd425f7e032f3&ns=2&cb=242625292\" async></script></body></html>`;
89

910
describe('#parseOpenAPI', () => {
10-
it('parses an OpenAPI document', async () => {
11+
it('parses a recursive OpenAPI document', async () => {
1112
const schema = await parseOpenAPI({
1213
value: spec,
1314
rootURL: null,
@@ -16,6 +17,15 @@ describe('#parseOpenAPI', () => {
1617
JSON.stringify(schema);
1718
});
1819

20+
it('parses a swagger v2', async () => {
21+
const schema = await parseOpenAPI({
22+
value: specV2,
23+
rootURL: null,
24+
});
25+
// Ensure the structure returned is not recursive (not dereferenced).
26+
JSON.stringify(schema);
27+
});
28+
1929
it('throws an error for invalid OpenAPI document', async () => {
2030
expect.assertions(1);
2131
try {

packages/openapi-parser/src/v2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ export async function convertOpenAPIV2ToOpenAPIV3(
2828
}
2929
})();
3030

31-
return parseOpenAPIV3({ ...input, rootURL, value: upgradeResult.specification });
31+
return parseOpenAPIV3({ ...input, rootURL, value: upgradeResult.specification, trust: true });
3232
}

packages/openapi-parser/src/v3.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ async function untrustedValidate(input: ValidateOpenAPIV3Input) {
3535
const { value, rootURL } = input;
3636
const result = await validate(value);
3737

38+
if (result.version === '2.0') {
39+
throw new OpenAPIParseError('Only OpenAPI v3 is supported', {
40+
code: 'parse-v2-in-v3',
41+
rootURL,
42+
});
43+
}
44+
3845
// Spec is invalid, we stop here.
3946
if (!result.valid) {
4047
throw new OpenAPIParseError('Invalid OpenAPI document', {
@@ -44,13 +51,6 @@ async function untrustedValidate(input: ValidateOpenAPIV3Input) {
4451
});
4552
}
4653

47-
if (result.version === '2.0') {
48-
throw new OpenAPIParseError('Only OpenAPI v3 is supported', {
49-
code: 'parse-v2-in-v3',
50-
rootURL,
51-
});
52-
}
53-
5454
return result.specification;
5555
}
5656

0 commit comments

Comments
 (0)