2019-05-13 08:56:06 +00:00
|
|
|
import fs from 'fs'
|
|
|
|
import path from 'path'
|
|
|
|
import http from 'http'
|
2019-07-06 01:06:07 +00:00
|
|
|
import matchRoute from 'my-way'
|
2019-05-26 10:30:45 +00:00
|
|
|
import serveHandler from 'serve-handler'
|
2019-05-13 08:13:19 +00:00
|
|
|
|
2019-05-14 01:36:25 +00:00
|
|
|
import serve404 from './libs/serve-404'
|
2019-05-13 08:13:19 +00:00
|
|
|
|
2019-07-04 10:11:23 +00:00
|
|
|
const sendError = (res: http.ServerResponse, error: Error) => {
|
2019-05-14 02:44:05 +00:00
|
|
|
res.statusCode = 500
|
|
|
|
res.end(error.message)
|
|
|
|
}
|
|
|
|
|
2019-07-04 10:11:23 +00:00
|
|
|
const sendRedirection = (res: http.ServerResponse, code: number, dest: string) => {
|
|
|
|
res.statusCode = code
|
|
|
|
res.setHeader('Location', dest)
|
|
|
|
res.end()
|
|
|
|
}
|
|
|
|
|
2019-11-18 15:52:07 +00:00
|
|
|
const badgeNames = fs.readdirSync(path.join(__dirname, 'api'))
|
2019-06-05 06:47:05 +00:00
|
|
|
.filter(name => /\.[jt]s$/.test(name))
|
|
|
|
.map(name => name.replace(/\.[jt]s$/, ''))
|
2019-05-13 08:13:19 +00:00
|
|
|
|
2019-05-26 10:30:45 +00:00
|
|
|
const isStatic = (url) => {
|
|
|
|
if (url === '/') return true
|
|
|
|
if (url.startsWith('/_next/')) return true
|
2019-06-05 06:47:05 +00:00
|
|
|
if (url.startsWith('/static/')) return true
|
|
|
|
if (url.startsWith('/builder')) return true
|
2019-05-26 10:30:45 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-06-07 12:34:26 +00:00
|
|
|
const serveStaticHeaders = [
|
|
|
|
{
|
2019-07-12 02:20:56 +00:00
|
|
|
source: '**/*',
|
2019-06-07 12:34:26 +00:00
|
|
|
headers: [{
|
2019-07-12 02:20:56 +00:00
|
|
|
key: 'Cache-Control',
|
|
|
|
value: 'public, max-age=86400, s-maxage=604800, stale-while-revalidate=86400'
|
2019-06-07 12:34:26 +00:00
|
|
|
}]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
2019-06-05 06:47:05 +00:00
|
|
|
const { PUB_DIR = '.' } = process.env
|
2019-05-14 02:44:05 +00:00
|
|
|
const server = http.createServer(async (req, res) => {
|
2019-07-04 10:11:23 +00:00
|
|
|
const url = req.url || '/'
|
|
|
|
|
2019-05-26 10:30:45 +00:00
|
|
|
// handle statics
|
2019-07-04 10:11:23 +00:00
|
|
|
if (isStatic(url)) {
|
2019-06-07 02:54:04 +00:00
|
|
|
return serveHandler(req, res, {
|
|
|
|
public: path.resolve(__dirname, PUB_DIR),
|
2019-06-07 12:34:26 +00:00
|
|
|
headers: serveStaticHeaders
|
2019-06-07 02:54:04 +00:00
|
|
|
})
|
2019-05-26 10:30:45 +00:00
|
|
|
}
|
|
|
|
|
2019-07-04 12:50:06 +00:00
|
|
|
// redirects `/docs/:name` to `/:name`
|
2019-07-04 10:11:23 +00:00
|
|
|
if (url.startsWith('/docs/')) {
|
|
|
|
return sendRedirection(res, 301, url.replace('/docs', ''))
|
2019-06-01 06:37:20 +00:00
|
|
|
}
|
|
|
|
|
2019-05-26 10:30:45 +00:00
|
|
|
// handle endpoints
|
2019-07-06 01:06:07 +00:00
|
|
|
const handlerName = badgeNames.find(h => matchRoute(`/${h}/:path*`, url))
|
2019-05-13 08:13:19 +00:00
|
|
|
|
2019-05-14 02:44:05 +00:00
|
|
|
try {
|
|
|
|
if (handlerName) {
|
2019-11-18 15:52:07 +00:00
|
|
|
const handlerPath = path.join(__dirname, 'api', handlerName)
|
2019-05-14 02:44:05 +00:00
|
|
|
const { default: handler } = await import(handlerPath)
|
2019-07-04 10:11:23 +00:00
|
|
|
return handler(req, res, handlerName)
|
2019-05-14 02:44:05 +00:00
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error)
|
2019-07-04 10:11:23 +00:00
|
|
|
return sendError(res, error)
|
2019-05-13 08:13:19 +00:00
|
|
|
}
|
2019-05-14 02:44:05 +00:00
|
|
|
|
|
|
|
return serve404(req, res)
|
2019-05-13 08:13:19 +00:00
|
|
|
})
|
2019-05-13 08:39:17 +00:00
|
|
|
|
2019-05-25 09:26:44 +00:00
|
|
|
// Auto run
|
2019-05-14 02:24:21 +00:00
|
|
|
if (require.main === module) {
|
2019-06-12 03:04:00 +00:00
|
|
|
const port = process.env.PORT || 3000
|
|
|
|
server.listen(port)
|
|
|
|
console.log(`Badgen listening on port ${port}`)
|
2019-05-13 08:39:17 +00:00
|
|
|
}
|
|
|
|
|
2019-06-01 06:37:20 +00:00
|
|
|
process.on('unhandledRejection', e => {
|
2019-07-04 10:11:23 +00:00
|
|
|
console.error('REJECTION', e)
|
2019-06-01 06:37:20 +00:00
|
|
|
})
|
|
|
|
|
2019-05-14 02:44:05 +00:00
|
|
|
export default server
|