You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wiki/server/modules/rendering/html-image-prefetch/renderer.js

46 lines
1.3 KiB

const request = require('request-promise')
const { URL } = require('url')
const BLOCKED_HOSTS = /^(127\.|10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|169\.254\.|::1$|::ffff:)/
function isSafeUrl (urlStr) {
let parsed
try { parsed = new URL(urlStr) } catch { return false }
if (!['http:', 'https:'].includes(parsed.protocol)) return false
if (parsed.hostname === 'localhost' || BLOCKED_HOSTS.test(parsed.hostname)) return false
return true
}
const prefetch = async (element) => {
const url = element.attr(`src`)
if (!isSafeUrl(url)) {
WIKI.logger.warn(`Blocked unsafe prefetch URL: ${url}`)
return
}
let response
try {
response = await request({
method: `GET`,
url,
resolveWithFullResponse: true
})
} catch (err) {
WIKI.logger.warn(`Failed to prefetch ${url}`)
WIKI.logger.warn(err)
return
}
const contentType = response.headers[`content-type`]
const image = Buffer.from(response.body).toString('base64')
element.attr('src', `data:${contentType};base64,${image}`)
element.removeClass('prefetch-candidate')
}
module.exports = {
async init($) {
const promises = $('img.prefetch-candidate').map((index, element) => {
return prefetch($(element))
}).toArray()
await Promise.all(promises)
}
}