// Add env vars from files // Note: actual env vars supersede .env file and .env file supersedes .env.defaults file require('dotenv-defaults').config() // Ignore paths for logging, metrics and docs const ignorePaths = ['/ready', '/healthy'] // Fast, minimalist web framework for node. const express = require('express') // Helmet helps you secure your Express app by setting various HTTP headers const helmet = require('helmet') // Very low overhead Node.js logger. Logs in json use pino-pretty for dev. const logger = require('pino')() // Fastest HTTP logger for Node.js in town const httpLogger = require('pino-http')({ logger, autoLogging: { ignorePaths } }) // Readiness and liveness checks middleware const health = require('@cloudnative/health-connect') const healthCheck = new health.HealthChecker() // Prometheus middleware for standard api metrics const apiMetrics = require('prometheus-api-metrics') // Swagger UI for api-docs const swaggerUi = require('swagger-ui-express') const yaml = require('js-yaml') const fs = require('fs') const swaggerDocument = yaml.load(fs.readFileSync('./swagger.yaml', 'utf8')) // 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 fetch = require('node-fetch') // Application-level middleware app.use(httpLogger) app.use(helmet()) app.use('/healthy', health.LivenessEndpoint(healthCheck)) app.use('/ready', health.ReadinessEndpoint(healthCheck)) app.use(apiMetrics({ excludeRoutes: ignorePaths })) app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)) app.use('/swagger.json', (req, res) => res.json(swaggerDocument)) const urls = yaml.load(fs.readFileSync('./config/manifests/url.yaml', 'utf8')).manifests app.get('/api/manifest.json', async (req, res, next) => { try { const results = urls.map(url => fetch(url).then(res => { if (!res.ok) throw new Error(`Failed to load manifest for url ${res.url} (Status: ${res.status}: ${res.statusText})`) return res.json().catch(err => { throw new Error(`Failed to load manifest for url ${res.url}: ${err}`) }) })) const content = await Promise.all(results) res.json(content.flat() || []) } catch (err) { next(err) } }) app.use(function (err, req, res, next) { logger.error(err) res.status(500).end() }) // Binds and listens for connections on the specified host and port app.listen(process.env.PORT, () => { logger.info(`manifest-service listening on port ${process.env.PORT}`) })