UNCLASSIFIED - NO CUI

Skip to content
Snippets Groups Projects
Verified Commit 0e73ed3a authored by Douglas Lagemann's avatar Douglas Lagemann
Browse files

Refactor to add controller

parent c89dd52a
No related branches found
No related tags found
1 merge request!5BULL-3221: express mvp
This commit is part of merge request !5. Comments created here will be created in the context of that merge request.
{
"name": "xx_project_name_xx-api",
"version": "1.0.0",
"private": true,
"version": "0.0.0",
"main": "app.js",
"scripts": {
"start": "node src/app.js",
"dev": "node src/app.js",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test": "echo \"Error: no test specified\" && exit 1"
"test:unit": "jest"
},
"dependencies": {
"express": "^4.21.1",
......@@ -16,6 +17,8 @@
"devDependencies": {
"@eslint/js": "^9.13.0",
"eslint": "^9.13.0",
"globals": "^15.11.0"
"globals": "^15.11.0",
"jest": "^29.7.0",
"supertest": "^7.0.0"
}
}
const express = require('express');
const { jwtDecode } = require('jwt-decode');
const { runMigrations, getDbVersion, healthCheck } = require('./data/dataLayer');
const { runMigrations } = require('./data/dataLayer');
const { getHealth, getVersion, getUser } = require('./controller/controller.js');
const app = express();
const port = 8000;
const apiVersion = "0.0.1";
// This middleware logs every incoming request with the current timestamp, HTTP method, and URL path.
app.use((req, res, next) => {
......@@ -17,57 +16,19 @@ app.get('/api', async (req, res) => {
res.send('Hello World! at specific path /api');
});
// Perform a health check by ensuring the data layer is healthy.
app.get('/api/health', async (req, res) => {
const dbHealth = await healthCheck();
if (dbHealth) {
res.status(dbHealth.status).json({
status: dbHealth.status,
message: dbHealth.message
});
} else {
res.status(500).json({
status: 500,
message: "Internal Server Error"
});
}
});
// Return the user's current JWT. Useful to ensure this is integrated properly in the Party Bus infrastructure.
app.get('/api/me', async (req, res) => {
try {
const header = req.headersDistinct?.Authorization?.[0] || req.headersDistinct?.authorization?.[0];
const responseData = header ? jwtDecode(header) : { result: "no authorization header found" };
res.json(responseData);
} catch (error) {
const errorResponse = {
error: 'Unable to read authorization header as jwt! Error: ' + error.message
}
res.json(errorResponse);
}
});
// Return basic version information. Useful to ensure this can query from its database.
app.get('/api/version', async (req, res) => {
const dbVersion = await getDbVersion();
const versionResponse = {
apiVersion: apiVersion,
dbVersion: dbVersion
};
res.json(versionResponse);
});
app.get('/api/health', getHealth);
app.get('/api/me', getUser);
app.get('/api/version', getVersion);
// This route handles all other paths not previously defined.
// It ensures that any undefined route still returns a 200 status with the path accessed.
// In many applications, this should return a 404.
// This route handles all other paths not previously defined by returning a 404.
app.all('*', async (req, res) => {
res.status(200).send(`Hello World! at general path ${req.path}`);
res.status(404).send(`Not found: ${req.path}`);
});
// This middleware catches any errors that occur in the request-processing pipeline.
// This middleware catches any errors that occur in the request processing pipeline.
// It logs the error details and sends a 500 Internal Server Error response.
// Consider expanding on this to inspect the error and return a status code based on known error conditions,
// or keep it only as a failsafe for any unhandled errors.
// or keep it as a failsafe to ensure sensitive information about the system is not returned.
app.use(async (err, req, res, next) => {
const timestamp = new Date().toISOString();
console.error(`[${timestamp}] Error: ${err.message}`);
......@@ -75,7 +36,7 @@ app.use(async (err, req, res, next) => {
res.status(500).send('Internal Server Error');
});
// Run database migrations to ensure the database is up to date, then start the api server!
// Run database migrations to ensure the database is up to date, then start the api server.
runMigrations().then(
app.listen(port, () => {
console.log(`App is running at http://localhost:${port}`);
......
const { getDbVersion, healthCheck } = require('../data/dataLayer');
const { jwtDecode } = require('jwt-decode');
const apiVersion = "0.0.1";
/**
* Perform a health check by ensuring data layer connectivity is healthy.
* */
exports.getHealth = async (req, res) => {
const dbHealth = await healthCheck();
if (!dbHealth) {
console.log("Unable to get DB health, returning 500 response");
res.status(500).json({
status: 500,
message: "Internal Server Error"
});
return;
}
let statusCode = 500;
if (dbHealth.healthy) {
statusCode = 200;
}
res.status(statusCode).json({
status: statusCode,
message: dbHealth.message
});
};
/**
* Return the user's current JWT. Useful to ensure that the app is integrated properly in the Party Bus infrastructure.
*/
exports.getUser = async (req, res) => {
try {
const header = req.headersDistinct?.Authorization?.[0] || req.headersDistinct?.authorization?.[0];
const responseData = header ? jwtDecode(header) : { result: "no authorization header found" };
res.json(responseData);
} catch (error) {
const errorResponse = {
error: 'Unable to read authorization header as jwt! Error: ' + error.message
}
res.status(400).json(errorResponse);
}
};
/**
* Return basic version information. Useful to check that the app can query from its database.
*/
exports.getVersion = async (req, res) => {
const dbVersion = await getDbVersion();
const versionResponse = {
apiVersion: apiVersion,
dbVersion: dbVersion
};
res.json(versionResponse);
};
// This file contains stubs to create an interface for the main app to reach out to a database.
// When building a fiesta-wagon project, if a database is selected, these will be replaced with fully-implemented functions.
// If there is no database required, these can be safely removed.
// If there is no database required, these functions can be removed.
/**
* Stub to run database migrations.
......@@ -13,7 +13,7 @@ exports.runMigrations = async () => {
*/
exports.healthCheck = async () => {
return {
status: 200,
healthy: true,
message: "Health check succeeded, but no database is deployed"
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment