Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save midnightcodr/25a7817bdb5efa00b83b7f58dae76090 to your computer and use it in GitHub Desktop.
Save midnightcodr/25a7817bdb5efa00b83b7f58dae76090 to your computer and use it in GitHub Desktop.
hapijs uploads: basic and advanced (with virus scanning) examples
const Hapi = require('@hapi/hapi')
const fs = require('fs')
const handleFileUpload = file => {
return new Promise((resolve, reject) => {
const { filename } = file.hapi
const outFile = fs.createWriteStream(`./uploads/${filename}`)
file
.pipe(outFile)
.on('error', err => {
console.error(err)
reject(err)
})
.on('close', () => {
console.log('done')
resolve({
message: 'uploaded'
})
})
})
}
;(async () => {
const server = Hapi.server({
port: 3000
})
server.route({
path: '/upload',
method: 'POST',
options: {
payload: {
maxBytes: 1024 * 1024 * 100, // max 100MB
parse: true,
output: 'stream',
allow: 'multipart/form-data',
multipart: true
}
},
handler (request) {
return handleFileUpload(request.payload.file)
}
})
await server.start()
console.log('start started at %s', server.info.uri)
})()
const Hapi = require('@hapi/hapi')
const fs = require('fs')
const NodeClam = require('clamscan')
const clamav = new NodeClam()
const handleFileUpload = (file, clamav) => {
return new Promise((resolve, reject) => {
const { filename } = file.hapi
const dest = `./uploads/${filename}`
const outFile = fs.createWriteStream(dest)
const av = clamav.passthrough()
av.on('scan-complete', result => {
console.log(result)
if (result.is_infected) {
console.warn(`${filename} is infected with [${result.viruses}]`)
fs.rename(dest, `${dest}.infected`, () => {})
}
})
file
.pipe(av)
.pipe(outFile)
.on('error', err => {
console.error(err)
reject(err)
})
.on('close', () => {
console.log('done')
resolve({
message: 'uploaded'
})
})
})
}
;(async () => {
const server = Hapi.server({
port: 3000
})
server.route({
path: '/upload',
method: 'POST',
options: {
payload: {
maxBytes: 1024 * 1024 * 100, // max 100MB
parse: true,
output: 'stream',
allow: 'multipart/form-data',
multipart: true
}
},
handler (request) {
return handleFileUpload(request.payload.file, request.server.clamav)
}
})
await clamav.init({
clamdscan: {
host: '127.0.0.1',
port: 3310
}
})
server.decorate('server', 'clamav', clamav)
await server.start()
console.log('start started at %s', server.info.uri)
})()

Setup

npm i

Use this docker image to setup the scanner

 docker run --name clamav -d -p 3310:3310 mkodockx/docker-clamav

Run

node main.js

In a seperate terminal, run

curl localhost:3000/upload -F 'file=@/path/to/file.ext'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment