2021-07-08 00:15:27 +00:00
|
|
|
import path from 'path'
|
2022-01-12 23:13:09 +00:00
|
|
|
import AWS from 'aws-sdk'
|
2022-11-06 17:28:58 +00:00
|
|
|
import { PassThrough } from 'stream'
|
2021-11-30 15:35:17 +00:00
|
|
|
const { spawn } = require('child_process')
|
2022-02-05 17:29:41 +00:00
|
|
|
const encodeS3URI = require('node-s3-url-encode')
|
2021-11-30 15:35:17 +00:00
|
|
|
|
2022-01-12 23:13:09 +00:00
|
|
|
const bucketName = 'sn-capture'
|
|
|
|
const bucketRegion = 'us-east-1'
|
|
|
|
const contentType = 'image/png'
|
|
|
|
const bucketUrl = 'https://sn-capture.s3.amazonaws.com/'
|
|
|
|
const s3PathPrefix = process.env.NODE_ENV === 'development' ? 'dev/' : ''
|
2022-11-06 17:28:58 +00:00
|
|
|
let capturing = false
|
2021-07-08 00:15:27 +00:00
|
|
|
|
2022-01-12 23:13:09 +00:00
|
|
|
AWS.config.update({
|
|
|
|
region: bucketRegion
|
|
|
|
})
|
|
|
|
|
2021-07-08 00:15:27 +00:00
|
|
|
export default async function handler (req, res) {
|
2021-10-22 22:21:38 +00:00
|
|
|
return new Promise(resolve => {
|
2022-01-12 23:13:09 +00:00
|
|
|
const joinedPath = path.join(...(req.query.path || []))
|
2022-02-05 17:29:41 +00:00
|
|
|
const searchQ = req.query.q ? `?q=${req.query.q}` : ''
|
|
|
|
const s3PathPUT = s3PathPrefix + (joinedPath === '.' ? '_' : joinedPath) + searchQ
|
|
|
|
const s3PathGET = s3PathPrefix + (joinedPath === '.' ? '_' : joinedPath) + encodeS3URI(searchQ)
|
2022-02-24 03:02:23 +00:00
|
|
|
const url = process.env.PUBLIC_URL + '/' + joinedPath + searchQ
|
2022-11-06 17:28:58 +00:00
|
|
|
const aws = new AWS.S3({ apiVersion: '2006-03-01' })
|
2021-10-22 22:21:38 +00:00
|
|
|
|
2022-01-12 23:13:09 +00:00
|
|
|
// check to see if we have a recent version of the object
|
|
|
|
aws.headObject({
|
|
|
|
Bucket: bucketName,
|
2022-02-05 17:29:41 +00:00
|
|
|
Key: s3PathPUT,
|
2022-11-06 17:28:58 +00:00
|
|
|
IfModifiedSince: new Date(new Date().getTime() - 15 * 60000)
|
2022-01-12 23:13:09 +00:00
|
|
|
}).promise().then(() => {
|
|
|
|
// this path is cached so return it
|
2022-02-05 17:29:41 +00:00
|
|
|
res.writeHead(302, { Location: bucketUrl + s3PathGET }).end()
|
2021-10-22 22:21:38 +00:00
|
|
|
resolve()
|
2022-01-12 23:13:09 +00:00
|
|
|
}).catch(() => {
|
|
|
|
// we don't have it cached, so capture it and cache it
|
2022-01-13 01:35:17 +00:00
|
|
|
if (capturing) {
|
|
|
|
return res.writeHead(503, {
|
2022-11-06 17:28:58 +00:00
|
|
|
'Retry-After': 1
|
2022-01-13 01:35:17 +00:00
|
|
|
}).end()
|
|
|
|
}
|
|
|
|
|
2022-01-12 23:13:09 +00:00
|
|
|
capturing = true
|
|
|
|
const pass = new PassThrough()
|
|
|
|
aws.upload({
|
|
|
|
Bucket: bucketName,
|
2022-02-05 17:29:41 +00:00
|
|
|
Key: s3PathPUT,
|
2022-01-12 23:13:09 +00:00
|
|
|
ACL: 'public-read',
|
|
|
|
Body: pass,
|
|
|
|
ContentType: contentType
|
|
|
|
}).promise().catch(console.log)
|
|
|
|
|
|
|
|
res.setHeader('Content-Type', contentType)
|
|
|
|
const capture = spawn(
|
2022-11-06 17:28:58 +00:00
|
|
|
'node', ['./spawn/capture.js', url], { maxBuffer: 1024 * 1024 * 5 })
|
2022-01-12 23:13:09 +00:00
|
|
|
|
|
|
|
capture.on('close', code => {
|
|
|
|
if (code !== 0) {
|
|
|
|
res.status(500).end()
|
|
|
|
} else {
|
|
|
|
res.status(200).end()
|
|
|
|
}
|
|
|
|
pass.end()
|
|
|
|
capture.removeAllListeners()
|
|
|
|
capturing = false
|
|
|
|
resolve()
|
|
|
|
})
|
|
|
|
capture.on('error', err => console.log('error', err))
|
|
|
|
capture.stderr.on('data', data => console.log('error stderr', data.toString()))
|
|
|
|
capture.stdout.on('data', data => {
|
|
|
|
res.write(data)
|
|
|
|
pass.write(data)
|
|
|
|
})
|
2021-10-22 22:21:38 +00:00
|
|
|
})
|
|
|
|
})
|
2022-11-06 17:28:58 +00:00
|
|
|
}
|