mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-10-04 04:21:33 +00:00
Integrate GitBook image resizing service and remove cdn-cgi mode (#4285)
This commit is contained in:
@@ -57,7 +57,8 @@ runs:
|
||||
GITBOOK_INTEGRATIONS_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_HOST
|
||||
GITBOOK_INTEGRATIONS_CONTENT_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_CONTENT_HOST
|
||||
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SIGNING_KEY
|
||||
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL
|
||||
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL_2
|
||||
GITBOOK_IMAGE_RESIZE_SALT: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SALT
|
||||
GITBOOK_IMAGE_RESIZE_MODE: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_MODE
|
||||
GITBOOK_ASSETS_PREFIX: ${{ inputs.opItem }}/GITBOOK_ASSETS_PREFIX
|
||||
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
|
||||
|
||||
@@ -59,7 +59,8 @@ runs:
|
||||
GITBOOK_INTEGRATIONS_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_HOST
|
||||
GITBOOK_INTEGRATIONS_CONTENT_HOST: ${{ inputs.opItem }}/GITBOOK_INTEGRATIONS_CONTENT_HOST
|
||||
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SIGNING_KEY
|
||||
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL
|
||||
GITBOOK_IMAGE_RESIZE_URL: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_URL_2
|
||||
GITBOOK_IMAGE_RESIZE_SALT: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_SALT
|
||||
GITBOOK_IMAGE_RESIZE_MODE: ${{ inputs.opItem }}/GITBOOK_IMAGE_RESIZE_MODE
|
||||
GITBOOK_ASSETS_PREFIX: ${{ inputs.opItem }}/GITBOOK_ASSETS_PREFIX
|
||||
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
|
||||
|
||||
@@ -50,6 +50,7 @@ const nextConfig = {
|
||||
GITBOOK_INTEGRATIONS_HOST: process.env.GITBOOK_INTEGRATIONS_HOST,
|
||||
GITBOOK_INTEGRATIONS_CONTENT_HOST: process.env.GITBOOK_INTEGRATIONS_CONTENT_HOST,
|
||||
GITBOOK_IMAGE_RESIZE_URL: process.env.GITBOOK_IMAGE_RESIZE_URL,
|
||||
GITBOOK_IMAGE_RESIZE_SALT: process.env.GITBOOK_IMAGE_RESIZE_SALT,
|
||||
GITBOOK_ICONS_URL: process.env.GITBOOK_ICONS_URL,
|
||||
GITBOOK_ICONS_TOKEN: process.env.GITBOOK_ICONS_TOKEN,
|
||||
GITBOOK_URL: process.env.GITBOOK_URL,
|
||||
|
||||
+3
-2
@@ -105,14 +105,15 @@ export const GITBOOK_FONTS_URL = process.env.GITBOOK_FONTS_URL || 'https://fonts
|
||||
export const GITBOOK_IMAGE_RESIZE_URL = process.env.GITBOOK_IMAGE_RESIZE_URL ?? null;
|
||||
export const GITBOOK_IMAGE_RESIZE_SIGNING_KEY =
|
||||
process.env.GITBOOK_IMAGE_RESIZE_SIGNING_KEY ?? null;
|
||||
export const GITBOOK_IMAGE_RESIZE_SALT = process.env.GITBOOK_IMAGE_RESIZE_SALT ?? null;
|
||||
|
||||
/**
|
||||
* Mode used for resizing images.
|
||||
*/
|
||||
export const GITBOOK_IMAGE_RESIZE_MODE = enforceEnum(
|
||||
'GITBOOK_IMAGE_RESIZE_MODE',
|
||||
process.env.GITBOOK_IMAGE_RESIZE_MODE || 'cdn-cgi',
|
||||
['cdn-cgi', 'cf-fetch']
|
||||
process.env.GITBOOK_IMAGE_RESIZE_MODE || 'cf-fetch',
|
||||
['cf-fetch', 'gitbook-service', 'cdn-cgi']
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import { GITBOOK_IMAGE_RESIZE_URL } from '@/lib/env';
|
||||
import { getLogger } from '@/lib/logger';
|
||||
import type { CloudflareImageOptions } from './types';
|
||||
import { copyImageResponse } from './utils';
|
||||
|
||||
/**
|
||||
* Resize an image by doing a request to a /cdn/cgi/ endpoint.
|
||||
* https://developers.cloudflare.com/images/transform-images/transform-via-url/
|
||||
*/
|
||||
export async function resizeImageWithCDNCgi(
|
||||
input: string,
|
||||
options: CloudflareImageOptions & {
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
): Promise<Response> {
|
||||
const { signal, ...resizeOptions } = options;
|
||||
|
||||
// Since Cloudflare Images options on fetch are not supported on Cloudflare Pages,
|
||||
// we need to use the Cloudflare Image Resize API directly.
|
||||
if (!GITBOOK_IMAGE_RESIZE_URL) {
|
||||
throw new Error('GITBOOK_IMAGE_RESIZE_URL is not set for cdn-cgi image resize mode');
|
||||
}
|
||||
|
||||
const resizeURL = `${GITBOOK_IMAGE_RESIZE_URL}${stringifyOptions(
|
||||
resizeOptions
|
||||
)}/${encodeURIComponent(input)}`;
|
||||
|
||||
const logger = getLogger().subLogger('imageResizing');
|
||||
logger.log(`resize image using cdn-cgi: ${resizeURL}`);
|
||||
|
||||
return copyImageResponse(
|
||||
await fetch(resizeURL, {
|
||||
headers: {
|
||||
// Pass the `Accept` header, as Cloudflare uses this to validate the format.
|
||||
Accept:
|
||||
resizeOptions.format === 'json'
|
||||
? 'application/json'
|
||||
: `image/${resizeOptions.format || 'jpeg'}`,
|
||||
},
|
||||
signal,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function stringifyOptions(options: CloudflareImageOptions): string {
|
||||
return Object.entries({ ...options }).reduce((rest, [key, value]) => {
|
||||
return `${rest}${rest ? ',' : ''}${key}=${value}`;
|
||||
}, '');
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { GITBOOK_IMAGE_RESIZE_SALT, GITBOOK_IMAGE_RESIZE_URL } from '@/lib/env';
|
||||
import { getLogger } from '@/lib/logger';
|
||||
import type { CloudflareImageOptions } from './types';
|
||||
import { copyImageResponse } from './utils';
|
||||
|
||||
function sdbmHash(str: string): number {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + (hash << 6) + (hash << 16) - hash;
|
||||
hash |= 0; // ensure 32-bit int
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize an image using the GitBook image service.
|
||||
* https://images.gitbook.com/__img/options/encoded-url
|
||||
*/
|
||||
export async function resizeImageWithGitbookServices(
|
||||
input: string,
|
||||
options: CloudflareImageOptions & {
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
): Promise<Response> {
|
||||
const { signal, ...resizeOptions } = options;
|
||||
|
||||
if (!GITBOOK_IMAGE_RESIZE_SALT) {
|
||||
throw new Error(
|
||||
'GITBOOK_IMAGE_RESIZE_SALT is not set for gitbook-service image resize mode'
|
||||
);
|
||||
}
|
||||
|
||||
if (!GITBOOK_IMAGE_RESIZE_URL) {
|
||||
throw new Error(
|
||||
'GITBOOK_IMAGE_RESIZE_URL is not set for gitbook-service image resize mode'
|
||||
);
|
||||
}
|
||||
|
||||
const signature = sdbmHash(`${input}:${GITBOOK_IMAGE_RESIZE_SALT}`).toString();
|
||||
const resizeURL = `${GITBOOK_IMAGE_RESIZE_URL}${stringifyOptions({
|
||||
...resizeOptions,
|
||||
signature,
|
||||
})}/${encodeURIComponent(input)}`;
|
||||
|
||||
const logger = getLogger().subLogger('imageResizing');
|
||||
logger.log(`resize image using gitbook-service: ${resizeURL}, format: ${resizeOptions.format}`);
|
||||
|
||||
return copyImageResponse(
|
||||
await fetch(resizeURL, {
|
||||
headers: {
|
||||
Accept:
|
||||
resizeOptions.format === 'json'
|
||||
? 'application/json'
|
||||
: `image/${resizeOptions.format || 'jpeg'}`,
|
||||
},
|
||||
signal,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function stringifyOptions(options: CloudflareImageOptions & { signature: string }): string {
|
||||
return Object.entries({ ...options }).reduce((rest, [key, value]) => {
|
||||
return `${rest}${rest ? ',' : ''}${key}=${value}`;
|
||||
}, '');
|
||||
}
|
||||
@@ -3,8 +3,8 @@ import { getLogger } from '@/lib/logger';
|
||||
import assertNever from 'assert-never';
|
||||
import { GITBOOK_IMAGE_RESIZE_MODE } from '../../env';
|
||||
import { SizableImageAction, checkIsSizableImageURL } from '../checkIsSizableImageURL';
|
||||
import { resizeImageWithCDNCgi } from './cdn-cgi';
|
||||
import { resizeImageWithCFFetch } from './cf-fetch';
|
||||
import { resizeImageWithGitbookServices } from './gitbook-service';
|
||||
import type { CloudflareImageJsonFormat, CloudflareImageOptions } from './types';
|
||||
|
||||
/**
|
||||
@@ -71,10 +71,11 @@ export async function resizeImage(
|
||||
}
|
||||
|
||||
switch (GITBOOK_IMAGE_RESIZE_MODE) {
|
||||
case 'cdn-cgi':
|
||||
return resizeImageWithCDNCgi(input, options);
|
||||
case 'cf-fetch':
|
||||
return resizeImageWithCFFetch(input, options);
|
||||
case 'gitbook-service':
|
||||
case 'cdn-cgi':
|
||||
return resizeImageWithGitbookServices(input, options);
|
||||
default:
|
||||
assertNever(GITBOOK_IMAGE_RESIZE_MODE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user