Fix admin paste URL proxy routing

This commit is contained in:
Codex
2026-06-01 14:30:43 +08:00
parent e7505eab4d
commit 521da2bb7a
2 changed files with 119 additions and 2 deletions
@@ -8,7 +8,46 @@ const pasteFetchCollectDelay = 300
const pasteFetchIdleReleaseDelay = 250
const pasteFetchRetryDelays = [0, 300, 800]
const pasteFetchConcurrency = 4
const pasteFetchPatchVersion = 4
const pasteFetchPatchVersion = 5
const bypassPathPrefixes = ['/admin', '/api', '/_next']
const assetPathPrefixes = ['/Attached/', '/Products/', '/Uploads/', '/controlapp/', '/files/', '/media/', '/videos/']
const assetExtensions = new Set([
'7z',
'aac',
'avi',
'bmp',
'css',
'csv',
'doc',
'docx',
'flac',
'gif',
'gz',
'htm',
'html',
'ico',
'jpeg',
'jpg',
'js',
'json',
'm4a',
'mov',
'mp3',
'mp4',
'pdf',
'png',
'rar',
'svg',
'tar',
'txt',
'wav',
'webm',
'webp',
'xls',
'xlsx',
'xml',
'zip',
])
type PatchedWindow = Window & {
__eversoloPasteURLFetchPatchVersion?: number
@@ -43,6 +82,23 @@ function getFetchMethod(input: RequestInfo | URL, init?: RequestInit) {
return undefined
}
function isBypassedURL(url: URL) {
if (url.origin === window.location.origin) return true
if (url.searchParams.has('_rsc')) return true
return bypassPathPrefixes.some((prefix) => {
return url.pathname === prefix || url.pathname.startsWith(`${prefix}/`)
})
}
function isAssetURL(url: URL) {
if (assetPathPrefixes.some((prefix) => url.pathname.startsWith(prefix))) return true
const extension = url.pathname.split('/').pop()?.split('.').pop()?.toLowerCase()
return extension ? assetExtensions.has(extension) : false
}
function getProxiedPasteURL(input: RequestInfo | URL, init?: RequestInit) {
const method = getFetchMethod(input, init)
@@ -57,6 +113,10 @@ function getProxiedPasteURL(input: RequestInfo | URL, init?: RequestInit) {
return null
}
if (isBypassedURL(url) || !isAssetURL(url)) {
return null
}
return `${proxyPath}?src=${encodeURIComponent(url.href)}`
} catch {
return null
+58 -1
View File
@@ -6,14 +6,71 @@ export const runtime = 'nodejs'
const retryDelays = [0, 300, 800, 1500]
const fetchTimeoutMs = 10000
const bypassPathPrefixes = ['/admin', '/api', '/_next']
const assetPathPrefixes = ['/Attached/', '/Products/', '/Uploads/', '/controlapp/', '/files/', '/media/', '/videos/']
const assetExtensions = new Set([
'7z',
'aac',
'avi',
'bmp',
'css',
'csv',
'doc',
'docx',
'flac',
'gif',
'gz',
'htm',
'html',
'ico',
'jpeg',
'jpg',
'js',
'json',
'm4a',
'mov',
'mp3',
'mp4',
'pdf',
'png',
'rar',
'svg',
'tar',
'txt',
'wav',
'webm',
'webp',
'xls',
'xlsx',
'xml',
'zip',
])
function isBypassedURL(url: URL) {
if (url.searchParams.has('_rsc')) return true
return bypassPathPrefixes.some((prefix) => {
return url.pathname === prefix || url.pathname.startsWith(`${prefix}/`)
})
}
function isAssetURL(url: URL) {
if (assetPathPrefixes.some((prefix) => url.pathname.startsWith(prefix))) return true
const extension = url.pathname.split('/').pop()?.split('.').pop()?.toLowerCase()
return extension ? assetExtensions.has(extension) : false
}
function isAllowedPasteURL(value: string) {
try {
const url = new URL(value)
return eversoloPasteURLAllowList.some((allowItem) => {
const hostIsAllowed = eversoloPasteURLAllowList.some((allowItem) => {
return url.protocol === `${allowItem.protocol}:` && url.hostname === allowItem.hostname
})
return hostIsAllowed && !isBypassedURL(url) && isAssetURL(url)
} catch {
return false
}