2018-12-11 15:31:48 +00:00
|
|
|
import * as sapper from '../__sapper__/server.js'
|
2019-02-15 03:39:24 +00:00
|
|
|
import express from 'express'
|
|
|
|
import compression from 'compression'
|
|
|
|
import serveStatic from 'serve-static'
|
|
|
|
import helmet from 'helmet'
|
|
|
|
import fetch from 'node-fetch'
|
|
|
|
import inlineScriptChecksum from './inline-script/checksum'
|
|
|
|
import { sapperInlineScriptChecksums } from './server/sapperInlineScriptChecksums'
|
2018-01-06 23:51:25 +00:00
|
|
|
|
2018-02-09 06:29:29 +00:00
|
|
|
const { PORT = 4002 } = process.env
|
2019-02-15 03:39:24 +00:00
|
|
|
const app = express()
|
2018-01-06 23:51:25 +00:00
|
|
|
|
2019-02-15 05:26:20 +00:00
|
|
|
const MAX_AGE = 3600
|
|
|
|
|
2018-02-08 16:22:14 +00:00
|
|
|
// this allows us to do e.g. `fetch('/_api/blog')` on the server
|
2018-01-06 23:51:25 +00:00
|
|
|
global.fetch = (url, opts) => {
|
2018-04-18 01:38:14 +00:00
|
|
|
if (url[0] === '/') {
|
|
|
|
url = `http://localhost:${PORT}${url}`
|
|
|
|
}
|
2018-02-09 06:29:29 +00:00
|
|
|
return fetch(url, opts)
|
|
|
|
}
|
2018-01-06 23:51:25 +00:00
|
|
|
|
2018-11-11 19:31:32 +00:00
|
|
|
app.use(compression({ threshold: 0 }))
|
2018-01-06 23:51:25 +00:00
|
|
|
|
2019-02-15 03:39:24 +00:00
|
|
|
// CSP only needs to apply to core HTML files, not debug files
|
|
|
|
// like report.html or the JS/CSS/JSON/image files
|
|
|
|
const coreHtmlFilesOnly = (fn) => (req, res, next) => {
|
|
|
|
let coreHtml = !/\.(js|css|json|png|svg|jpe?g|map)$/.test(req.path) &&
|
|
|
|
!(/\/report.html/.test(req.path))
|
|
|
|
return coreHtml ? fn(req, res, next) : next()
|
|
|
|
}
|
2018-12-11 15:31:48 +00:00
|
|
|
|
2019-02-15 03:39:24 +00:00
|
|
|
app.use(coreHtmlFilesOnly(helmet({
|
2018-04-15 22:39:45 +00:00
|
|
|
contentSecurityPolicy: {
|
|
|
|
directives: {
|
2018-12-11 15:31:48 +00:00
|
|
|
scriptSrc: [
|
|
|
|
`'self'`,
|
2019-02-15 03:39:24 +00:00
|
|
|
`'sha256-${inlineScriptChecksum}'`,
|
|
|
|
...sapperInlineScriptChecksums.map(_ => `'sha256-${_}'`)
|
2018-12-11 15:31:48 +00:00
|
|
|
],
|
2018-04-15 22:39:45 +00:00
|
|
|
workerSrc: [`'self'`],
|
|
|
|
styleSrc: [`'self'`, `'unsafe-inline'`],
|
|
|
|
frameSrc: [`'none'`],
|
|
|
|
objectSrc: [`'none'`],
|
|
|
|
manifestSrc: [`'self'`]
|
|
|
|
}
|
2018-04-20 04:38:22 +00:00
|
|
|
},
|
|
|
|
referrerPolicy: {
|
|
|
|
policy: 'no-referrer'
|
2018-04-14 22:50:16 +00:00
|
|
|
}
|
2018-04-18 01:38:14 +00:00
|
|
|
})))
|
2018-04-14 22:50:16 +00:00
|
|
|
|
2018-12-11 15:31:48 +00:00
|
|
|
app.use(serveStatic('static', {
|
2018-03-21 03:46:37 +00:00
|
|
|
setHeaders: (res) => {
|
2019-02-15 05:26:20 +00:00
|
|
|
res.setHeader('Cache-Control', `public,max-age=${MAX_AGE}`)
|
2018-03-21 03:46:37 +00:00
|
|
|
}
|
|
|
|
}))
|
2018-01-06 23:51:25 +00:00
|
|
|
|
2019-02-15 03:39:24 +00:00
|
|
|
app.use(express.static('__sapper__/build/client/report.html'))
|
|
|
|
app.use(express.static('__sapper__/build/client/stats.json'))
|
2018-03-25 20:47:01 +00:00
|
|
|
|
2019-02-15 06:54:18 +00:00
|
|
|
// TODO: hack to override Sapper's default cache-control
|
2019-02-15 05:26:20 +00:00
|
|
|
function overrideSetHeader (req, res, next) {
|
|
|
|
const origSetHeader = res.setHeader
|
|
|
|
res.setHeader = function (key, value) {
|
2019-02-15 06:54:18 +00:00
|
|
|
if (key === 'Cache-Control') {
|
|
|
|
if (value === 'max-age=31536000, immutable') { // webpack assets
|
|
|
|
return origSetHeader.apply(this, ['Cache-Control', 'public,max-age=31536000,immutable'])
|
|
|
|
}
|
|
|
|
if (value === 'max-age=600') { // HTML files
|
|
|
|
return origSetHeader.apply(this, ['Cache-Control', `public,max-age=${MAX_AGE}`])
|
|
|
|
}
|
2019-02-15 05:26:20 +00:00
|
|
|
}
|
2019-02-15 06:54:18 +00:00
|
|
|
|
2019-02-15 05:26:20 +00:00
|
|
|
return origSetHeader.apply(this, arguments)
|
|
|
|
}
|
|
|
|
return next()
|
|
|
|
}
|
|
|
|
|
|
|
|
app.use(overrideSetHeader, sapper.middleware())
|
2018-01-06 23:51:25 +00:00
|
|
|
|
|
|
|
app.listen(PORT, () => {
|
2018-02-09 06:29:29 +00:00
|
|
|
console.log(`listening on port ${PORT}`)
|
|
|
|
})
|
2018-05-25 02:59:48 +00:00
|
|
|
|
|
|
|
// Handle SIGINT (source: https://git.io/vhJgF)
|
|
|
|
process.on('SIGINT', function () {
|
|
|
|
process.exit(0)
|
|
|
|
})
|