tavern / SillyTavern-1.13.0 /src /fetch-patch.js
liucy98's picture
Upload 910 files
d44b3c1 verified
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import mime from 'mime-types';
import { serverDirectory } from './server-directory.js';
const originalFetch = globalThis.fetch;
const ALLOWED_EXTENSIONS = [
'.wasm',
];
/**
* Checks if a child path is under a parent path.
* @param {string} parentPath Parent path
* @param {string} childPath Child path
* @returns {boolean} Returns true if the child path is under the parent path, false otherwise
*/
function isPathUnderParent(parentPath, childPath) {
const normalizedParent = path.normalize(parentPath);
const normalizedChild = path.normalize(childPath);
const relativePath = path.relative(normalizedParent, normalizedChild);
return !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
}
/**
* Checks if the given request is a file URL.
* @param {string | URL | Request} request The request to check
* @return {boolean} Returns true if the request is a file URL, false otherwise
*/
function isFileURL(request) {
if (typeof request === 'string') {
return request.startsWith('file://');
}
if (request instanceof URL) {
return request.protocol === 'file:';
}
if (request instanceof Request) {
return request.url.startsWith('file://');
}
return false;
}
/**
* Gets the URL from the request.
* @param {string | URL | Request} request The request to get the URL from
* @return {string} The URL of the request
*/
function getRequestURL(request) {
if (typeof request === 'string') {
return request;
}
if (request instanceof URL) {
return request.href;
}
if (request instanceof Request) {
return request.url;
}
throw new TypeError('Invalid request type');
}
// Patched fetch function that handles file URLs
globalThis.fetch = async (/** @type {string | URL | Request} */ request, /** @type {RequestInit | undefined} */ options) => {
if (!isFileURL(request)) {
return originalFetch(request, options);
}
const url = getRequestURL(request);
const filePath = path.resolve(fileURLToPath(url));
const isUnderServerDirectory = isPathUnderParent(serverDirectory, filePath);
if (!isUnderServerDirectory) {
throw new Error('Requested file path is outside of the server directory.');
}
const parsedPath = path.parse(filePath);
if (!ALLOWED_EXTENSIONS.includes(parsedPath.ext)) {
throw new Error('Unsupported file extension.');
}
const fileName = parsedPath.base;
const buffer = await fs.promises.readFile(filePath);
const response = new Response(buffer, {
status: 200,
statusText: 'OK',
headers: {
'Content-Type': mime.lookup(fileName) || 'application/octet-stream',
'Content-Length': buffer.length.toString(),
},
});
return response;
};