mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2024-12-13 16:06:21 +00:00
feat: better size check for url uploads
first layer is via sending HEAD request to the url to determine its size via content-length header however not all hosts properly set the header, so we ignore it if it isn't a valid number next via size option in fetch(), which supposedly limits response body size during the request itself (?) lastly via checking actual bytes written to physical file as reported by fs.createWriteStream()
This commit is contained in:
parent
71a6adc3d3
commit
ce71a9e8d6
@ -30,7 +30,8 @@ const fileIdentifierLengthChangeable = !config.uploads.fileIdentifierLength.forc
|
||||
|
||||
const maxSize = parseInt(config.uploads.maxSize)
|
||||
const maxSizeBytes = maxSize * 1e6
|
||||
const urlMaxSizeBytes = parseInt(config.uploads.urlMaxSize) * 1e6
|
||||
const urlMaxSize = parseInt(config.uploads.urlMaxSize)
|
||||
const urlMaxSizeBytes = urlMaxSize * 1e6
|
||||
|
||||
const maxFilesPerUpload = 20
|
||||
|
||||
@ -382,6 +383,18 @@ self.actuallyUploadUrls = async (req, res, user, albumid, age) => {
|
||||
throw new ClientError(`Maximum ${maxFilesPerUpload} URLs at a time.`)
|
||||
}
|
||||
|
||||
const assertSize = (size, isContentLength = false) => {
|
||||
if (config.filterEmptyFile && size === 0) {
|
||||
throw new ClientError('Empty files are not allowed.')
|
||||
} else if (size > urlMaxSizeBytes) {
|
||||
if (isContentLength) {
|
||||
throw new ClientError(`File too large. Content-Length header reports file is bigger than ${urlMaxSize} MB.`)
|
||||
} else {
|
||||
throw new ClientError(`File too large. File is bigger than ${urlMaxSize} MB.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const downloaded = []
|
||||
const infoMap = []
|
||||
try {
|
||||
@ -419,8 +432,25 @@ self.actuallyUploadUrls = async (req, res, user, albumid, age) => {
|
||||
// Push to array early, so regardless of its progress it will be deleted on errors
|
||||
downloaded.push(destination)
|
||||
|
||||
// Try to determine size early via Content-Length header,
|
||||
// but continue anyway if it isn't a valid number
|
||||
try {
|
||||
const head = await fetch(url, { method: 'HEAD', size: urlMaxSizeBytes })
|
||||
if (head.status === 200) {
|
||||
const contentLength = parseInt(head.headers.get('content-length'))
|
||||
if (!Number.isNaN(contentLength)) {
|
||||
assertSize(contentLength, true)
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
// Re-throw only if ClientError, otherwise ignore
|
||||
if (ex instanceof ClientError) {
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
// Limit max response body size with maximum allowed size
|
||||
const fetchFile = await fetch(url, { size: urlMaxSizeBytes })
|
||||
const fetchFile = await fetch(url, { method: 'GET', size: urlMaxSizeBytes })
|
||||
.then(res => new Promise((resolve, reject) => {
|
||||
if (res.status === 200) {
|
||||
const onerror = error => {
|
||||
@ -443,6 +473,8 @@ self.actuallyUploadUrls = async (req, res, user, albumid, age) => {
|
||||
}
|
||||
|
||||
const contentType = fetchFile.headers.get('content-type')
|
||||
// Re-test size via actual bytes written to physical file
|
||||
assertSize(outStream.bytesWritten)
|
||||
|
||||
infoMap.push({
|
||||
path: destination,
|
||||
|
Loading…
Reference in New Issue
Block a user