benjaminvr

ApiServer for Express - NodeJS

Dec 6th, 2021 (edited)
260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /************************** Info
  2.     License: MIT license at bottom, nullifying any license stipulations of this platform
  3.    
  4.     Requirements: NodeJS with Express, Morgan packages
  5.     This is a substitute for the /bin/www and server.js file generated when creating an Express App.
  6.     This will not work out of the box, to make it work:
  7.         - optional - add API_PORT to .env
  8.         - remove reference to JsonParseCatch, hardcode it, or create the file
  9.         - redefine ApiEndpoints and its usage in useRoutes, or create file at that path
  10.         - remove references to routes, and add your own
  11.        
  12.         - Change npm start command in package.json, or run directly with "node ApiServer.js"
  13. */
  14.  
  15. /************************** JsonParseCatch.js
  16.     Optional middleware, prevents Express from crashing when parsing JSON.
  17.     Save in ./Middleware/JsonParseCatch.js, or elsewhere and modify reference
  18. */
  19. const JsonParseCatch = (err, req, res, next) => {
  20.     if(err instanceof SyntaxError && err.status === 400 && "body" in err){
  21.             return res.status(400).send({status: 400, message: err.message});
  22.     }
  23.     next();
  24. }
  25.  
  26. module.exports = {
  27.     JsonParseCatch: JsonParseCatch,
  28.     router: require("express").Router()
  29. };
  30.  
  31. /************************** ApiServer.js */
  32. require("dotenv").config();
  33.  
  34. class ApiServer {
  35.     constructor() {
  36.         this.ApiEndpoints = require("./Static/Shared/Config").ApiEndpoints;
  37.         this.logger = require("morgan")("dev");
  38.         this.port = this.normalizePort(process.env.API_PORT) || 3000;
  39.         this.httpServer = (this.http = require("http")).createServer(this.app = (this.express = require("express"))());
  40.     }
  41.  
  42.     run = () => {
  43.         this.setConfig();
  44.         this.setMiddleware();
  45.         this.setRoutes();
  46.         this.startListening();
  47.     }
  48.  
  49.     setConfig = () => {
  50.         this.app.use(this.logger);
  51.         this.app.use(this.express.json());
  52.     }
  53.  
  54.     setMiddleware = () => {
  55.         this.app.use(require("./Middleware/JsonParseCatch").JsonParseCatch);
  56.     }
  57.  
  58.     setRoutes = () => {
  59.         let homeRouter = require("./Routes/HomeRouter");
  60.         let productRouter = require("./Routes/ProductRouter");
  61.  
  62.         /*
  63.             GET /products
  64.             Returns:        Array of products
  65.             Beschrijving:   Get all products
  66.         */
  67.         this.app.use(this.ApiEndpoints.Products, productRouter);
  68.        
  69.         /*
  70.             GET /
  71.             Returns:        Metric
  72.             Beschrijving:   Get metrics
  73.         */
  74.         this.app.use(this.ApiEndpoints.Metrics, homeRouter);
  75.     }
  76.  
  77.     startListening = () => {
  78.         this.httpServer.listen(this.port);
  79.         this.httpServer.on('error', this.onError);
  80.         this.httpServer.on('listening', this.onListening);
  81.     }
  82.  
  83.     normalizePort = (val) => {
  84.         let port; return port = parseInt(val, 10), isNaN(port) ? val : port >= 0 ? port : false;
  85.     }
  86.  
  87.     onError = (error) => {
  88.         error.syscall !== "listen" ? (() => { throw error; }).call() : null;
  89.  
  90.         let bind = typeof this.port === 'string' ? 'Pipe ' + this.port : 'Port ' + this.port;
  91.  
  92.         switch (error.code) {
  93.             case 'EACCES':
  94.                 console.error('[ApiServer - onError.EACCES] ' + bind + ' requires elevated privileges');
  95.                 process.exit(1);
  96.                 break;
  97.             case 'EADDRINUSE':
  98.                 console.error('[ApiServer - onError.EADDRINUSE] ' + bind + ' is already in use');
  99.                 process.exit(1);
  100.                 break;
  101.             default:
  102.                 throw error;
  103.         }
  104.     }
  105.  
  106.     onListening = () => {
  107.         let addr = this.httpServer.address();
  108.         let bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
  109.         console.log('[ApiServer - onListening] API server listening on ' + bind);
  110.     }
  111. }
  112.  
  113. const server = new ApiServer().run();
  114.  
  115. /* Author: Benjamin Van Renterghem
  116.  *
  117.  * Permission is hereby granted, free of charge, to any person obtaining
  118.  * a copy of this software and associated documentation files (the
  119.  * "Software"), to deal in the Software without restriction, including
  120.  * without limitation the rights to use, copy, modify, merge, publish,
  121.  * distribute, sublicense, and/or sell copies of the Software, and to
  122.  * permit persons to whom the Software is furnished to do so, subject to
  123.  * the following conditions:
  124.  *
  125.  * The above copyright notice and this permission notice shall be
  126.  * included in all copies or substantial portions of the Software.
  127.  *
  128.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  129.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  130.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  131.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  132.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  133.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  134.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
Add Comment
Please, Sign In to add comment