haraka-tld
Version:
Haraka TLD utilities
78 lines (66 loc) • 2.08 kB
JavaScript
const fs = require('node:fs')
const fsp = require('node:fs/promises')
const path = require('node:path')
const { Readable } = require('node:stream')
const { pipeline } = require('node:stream/promises')
const CommentStripper = require('./comment-stripper')
const pslFile = path.resolve(__dirname, '..', 'etc', 'public-suffix-list')
const PSL_URL = 'https://publicsuffix.org/list/effective_tld_names.dat'
const UA_HEADER = { 'User-Agent': 'Haraka-TLD' }
exports.updatePSLfile = async (opts = {}) => {
const isNewer = await exports.isRemoteNewer(pslFile, opts)
if (!isNewer) return false
await exports.download(pslFile, opts)
return true
}
exports.getFileStats = async (filePath = pslFile) => {
try {
const stats = await fsp.stat(filePath)
if (stats.isFile()) return stats
if (stats.isDirectory()) {
await fsp.rmdir(filePath)
} else {
await fsp.unlink(filePath)
}
return null
} catch {
return null
}
}
exports.isRemoteNewer = async (dest, opts = {}) => {
if (!dest) dest = pslFile
const fetchImpl = opts.fetch ?? fetch
const url = opts.url ?? PSL_URL
const stats = await exports.getFileStats(dest)
const headers = { ...UA_HEADER }
if (stats) headers['If-Modified-Since'] = stats.mtime.toUTCString()
try {
const res = await fetchImpl(url, {
method: 'HEAD',
headers,
signal: AbortSignal.timeout(30_000),
})
return res.status === 200
} catch {
return false
}
}
exports.download = async (dest, opts = {}) => {
if (!dest) dest = pslFile
const fetchImpl = opts.fetch ?? fetch
const url = opts.url ?? PSL_URL
const tmpFile = `${dest}.tmp`
const res = await fetchImpl(url, {
headers: UA_HEADER,
signal: AbortSignal.timeout(60_000),
})
if (!res.ok) throw new Error(`response code ${res.status} not handled!`)
try {
await pipeline(Readable.fromWeb(res.body), new CommentStripper(), fs.createWriteStream(tmpFile))
await fsp.rename(tmpFile, dest)
} catch (err) {
await fsp.unlink(tmpFile).catch(() => {})
throw err
}
return true
}