Fix admin paste URL proxy routing
This commit is contained in:
@@ -8,7 +8,46 @@ const pasteFetchCollectDelay = 300
|
|||||||
const pasteFetchIdleReleaseDelay = 250
|
const pasteFetchIdleReleaseDelay = 250
|
||||||
const pasteFetchRetryDelays = [0, 300, 800]
|
const pasteFetchRetryDelays = [0, 300, 800]
|
||||||
const pasteFetchConcurrency = 4
|
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 & {
|
type PatchedWindow = Window & {
|
||||||
__eversoloPasteURLFetchPatchVersion?: number
|
__eversoloPasteURLFetchPatchVersion?: number
|
||||||
@@ -43,6 +82,23 @@ function getFetchMethod(input: RequestInfo | URL, init?: RequestInit) {
|
|||||||
return undefined
|
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) {
|
function getProxiedPasteURL(input: RequestInfo | URL, init?: RequestInit) {
|
||||||
const method = getFetchMethod(input, init)
|
const method = getFetchMethod(input, init)
|
||||||
|
|
||||||
@@ -57,6 +113,10 @@ function getProxiedPasteURL(input: RequestInfo | URL, init?: RequestInit) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isBypassedURL(url) || !isAssetURL(url)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return `${proxyPath}?src=${encodeURIComponent(url.href)}`
|
return `${proxyPath}?src=${encodeURIComponent(url.href)}`
|
||||||
} catch {
|
} catch {
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -6,14 +6,71 @@ export const runtime = 'nodejs'
|
|||||||
|
|
||||||
const retryDelays = [0, 300, 800, 1500]
|
const retryDelays = [0, 300, 800, 1500]
|
||||||
const fetchTimeoutMs = 10000
|
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) {
|
function isAllowedPasteURL(value: string) {
|
||||||
try {
|
try {
|
||||||
const url = new URL(value)
|
const url = new URL(value)
|
||||||
|
|
||||||
return eversoloPasteURLAllowList.some((allowItem) => {
|
const hostIsAllowed = eversoloPasteURLAllowList.some((allowItem) => {
|
||||||
return url.protocol === `${allowItem.protocol}:` && url.hostname === allowItem.hostname
|
return url.protocol === `${allowItem.protocol}:` && url.hostname === allowItem.hostname
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return hostIsAllowed && !isBypassedURL(url) && isAssetURL(url)
|
||||||
} catch {
|
} catch {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user