Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/gitbook/e2e/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ export function runTestCases(testCases: TestsCase[]) {
}))
);
}

// Disable the Vercel toolbar
await page.setExtraHTTPHeaders({
'x-vercel-skip-toolbar': '1',
});

await page.goto(url);
if (testEntry.run) {
await testEntry.run(page);
Expand Down
76 changes: 52 additions & 24 deletions packages/gitbook/src/lib/openapi/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { GitBookAnyContext } from '@v2/lib/context';
import { type CacheFunctionOptions, cache, noCacheFetchOptions } from '@/lib/cache';

import { resolveContentRef } from '../references';
import { isV2 } from '../v2';
import { enrichFilesystem } from './enrich';

const weakmap = new WeakMap<DocumentBlockOpenAPI, ResolveOpenAPIBlockResult>();
Expand Down Expand Up @@ -65,32 +66,18 @@ async function baseResolveOpenAPIBlock(args: ResolveOpenAPIBlockArgs): ResolveOp
}
}

const fetchFilesystem = cache({
name: 'openapi.fetch.v6',
get: async (url: string, options: CacheFunctionOptions) => {
// Wrap the raw string to prevent invalid URLs from being passed to fetch.
// This can happen if the URL has whitespace, which is currently handled differently by Cloudflare's implementation of fetch:
// https://github.com/cloudflare/workerd/issues/1957
const response = await fetch(new URL(url), {
...noCacheFetchOptions,
signal: options.signal,
});
function fetchFilesystem(url: string) {
if (isV2()) {
return fetchFilesystemV2(url);
}

if (!response.ok) {
throw new Error(
`Failed to fetch OpenAPI file: ${response.status} ${response.statusText}`
);
}
return fetchFilesystemV1(url);
}

const text = await response.text();
const filesystem = await parseOpenAPI({
value: text,
rootURL: url,
// If we fetch the OpenAPI specification
// it's the legacy system, it means the spec can be trusted here.
trust: true,
});
const richFilesystem = await enrichFilesystem(filesystem);
const fetchFilesystemV1 = cache({
name: 'openapi.fetch.v6',
get: async (url: string, options: CacheFunctionOptions) => {
const richFilesystem = await fetchFilesystemUncached(url, options);
return {
// Cache for 4 hours
ttl: 24 * 60 * 60,
Expand All @@ -100,3 +87,44 @@ const fetchFilesystem = cache({
};
},
});

async function fetchFilesystemV2(url: string) {
'use cache';

// TODO: add cache lifetime once we can use next.js 15 code here

const response = await fetchFilesystemUncached(url);

return response;
}

async function fetchFilesystemUncached(
url: string,
options?: {
signal?: AbortSignal;
}
) {
// Wrap the raw string to prevent invalid URLs from being passed to fetch.
// This can happen if the URL has whitespace, which is currently handled differently by Cloudflare's implementation of fetch:
// https://github.com/cloudflare/workerd/issues/1957
const response = await fetch(new URL(url), {
...noCacheFetchOptions,
signal: options?.signal,
});

if (!response.ok) {
throw new Error(`Failed to fetch OpenAPI file: ${response.status} ${response.statusText}`);
}

const text = await response.text();
const filesystem = await parseOpenAPI({
value: text,
rootURL: url,
// If we fetch the OpenAPI specification
// it's the legacy system, it means the spec can be trusted here.
trust: true,
});
const richFilesystem = await enrichFilesystem(filesystem);

return richFilesystem;
}
9 changes: 8 additions & 1 deletion packages/gitbook/src/lib/v2.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
/**
* Check if the code is running in v2.
*/
export function isV2() {
return process.env.GITBOOK_V2 === 'true';
}

/**
* Assert that the code is not running in v2.
*/
export function assertIsNotV2() {
if (process.env.GITBOOK_V2 === 'true') {
if (isV2()) {
throw new Error('This code is not available in V2');
}
}
7 changes: 3 additions & 4 deletions packages/react-openapi/src/OpenAPICodeSample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { generateMediaTypeExample, generateSchemaExample } from './generateSchem
import { stringifyOpenAPI } from './stringifyOpenAPI';
import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
import { getDefaultServerURL } from './util/server';
import { createStateKey } from './utils';
import { checkIsReference } from './utils';
import { checkIsReference, createStateKey } from './utils';

/**
* Display code samples to execute the operation.
Expand Down Expand Up @@ -95,8 +94,8 @@ export function OpenAPICodeSample(props: {
typeof sample.lang === 'string'
);
})
.map((sample) => ({
key: `redocly-${sample.lang}`,
.map((sample, index) => ({
key: `redocly-${sample.lang}-${index}`,
label: sample.label,
body: context.renderCodeBlock({
code: sample.source,
Expand Down
Loading