-
julian.baeume authored
first hit wins. This allows us to transparently use sourcemaps and other files that are not part of the sources according to the vite manifest
julian.baeume authoredfirst hit wins. This allows us to transparently use sourcemaps and other files that are not part of the sources according to the vite manifest
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
createApp.js 3.28 KiB
// Ignore paths for logging, metrics and docs
// Fast, minimalist web framework for node.
import express from 'express'
// Helmet helps you secure your Express app by setting various HTTP headers
import helmet from 'helmet'
// Fastest HTTP logger for Node.js in town
import { getLogger } from './logger.js'
import pinoHttp from 'pino-http'
// Readiness and liveness checks middleware
import health from '@cloudnative/health-connect'
// Prometheus middleware for standard api metrics
import promBundle from 'express-prom-bundle'
// Swagger UI for api-docs
import swaggerUi from 'swagger-ui-express'
import yaml from 'js-yaml'
import fs from 'fs'
import { getDependencies, getOxManifests } from './manifests.js'
import { fileCache } from './files.js'
const ignorePaths = ['/ready', '/healthy']
const swaggerDocument = yaml.load(fs.readFileSync('./src/swagger.yaml', 'utf8'))
const bypass = (request) => ignorePaths.includes(request.path)
const metricsMiddleware = promBundle({ bypass })
export function createApp () {
// The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.
const app = express()
const logger = getLogger()
const httpLogger = pinoHttp({ logger, autoLogging: { ignorePaths } })
const healthCheck = new health.HealthChecker()
const readinessCheck = new health.ReadinessCheck('getDependencies', async function () {
try {
await getDependencies()
} catch (e) {
logger.error(`Failed to get dependencies: ${e.message}`)
throw e
}
})
healthCheck.registerReadinessCheck(readinessCheck)
// Application-level middleware
app.use(httpLogger)
app.use((req, res, next) => {
const { sha256Sum } = fileCache.get(req.path)
res.locals.sha256Sum = sha256Sum
next()
})
app.use(helmet({
contentSecurityPolicy: false
}))
app.use('/healthy', health.LivenessEndpoint(healthCheck))
app.use('/ready', health.ReadinessEndpoint(healthCheck))
app.use(metricsMiddleware)
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
app.timeout = 30000
app.get('/api/manifest.json', async (req, res, next) => {
try {
res.json(await getOxManifests())
} catch (err) {
next(err)
}
})
app.get('/api/deps.json', async (req, res, next) => {
try {
res.json(await getDependencies())
} catch (err) {
next(err)
}
})
app.get('/', async (req, res, next) => {
const { 'content-type': contentType, content } = fileCache.get('/index.html')
if (content) return res.setHeader('content-type', contentType).status(200).send(content)
next()
})
app.use(async (req, res, next) => {
const { 'content-type': contentType, content } = fileCache.get(req.path)
if (content) return res.setHeader('content-type', contentType).status(200).send(content)
next()
})
app.use(async (req, res, next) => {
try {
const { 'content-type': contentType, content } = await fileCache.fetchAndStore(req.path)
if (content) return res.setHeader('content-type', contentType).status(200).send(content)
} catch (e) {}
next()
})
app.use(function (err, req, res, next) {
logger.error(err)
res.status(500).end()
})
return app
}