You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

221 lines
5.3 KiB

/*!
* lib/http-server/http-server.js
* Copyright © 2019 – Katana Cryptographic Ltd. All Rights Reserved.
*/
'use strict'
const fs = require('fs')
const express = require('express')
const helmet = require('helmet')
const Logger = require('../logger')
/**
* HTTP server
*/
class HttpServer {
/**
* Constructor
* @param {int} port - port used by the http server
* @param {string} host - host exposing the http server
*/
constructor(port, host) {
// Initialize server host and port
this.host = host ? host : '127.0.0.1'
this.port = port
// Listening server instance
this.server = null
// Initialize the express app
this.app = express()
this.app.set('trust proxy', 'loopback')
// Middlewares for json responses and requests logging
this.app.use('/static', express.static('../static'));
this.app.use(HttpServer.setJSONResponse)
this.app.use(HttpServer.requestLogger)
this.app.use(HttpServer.setCrossOrigin)
this.app.use(HttpServer.setConnection)
this.app.use(helmet(HttpServer.HELMET_POLICY))
}
/**
* Start the http server
* @returns {object} returns the listening server instance
*/
start() {
// Error handler, should be final middleware
this.app.use(function(err, req, res, next) {
if (res.headersSent) return next(err)
Logger.error(err.stack, 'HttpServer : start()')
const ret = {status: 'Server error'}
HttpServer.sendError(res, ret, 500)
})
// Start a http server
this.server = this.app.listen(this.port, this.host, () => {
Logger.info(`HttpServer : Listening on ${this.host}:${this.port}`)
})
this.server.timeout = 600 * 1000
// @see https://github.com/nodejs/node/issues/13391
this.server.keepAliveTimeout = 0
return this.server
}
/**
* Stop the http server
*/
stop() {
if (this.app === null) return
this.app.close()
}
/**
* Return a http response without data
* @param {object} res - http response object
*/
static sendOk(res) {
const ret = {status: 'ok'}
res.status(200).json(ret)
}
/**
* Return a http response without status
* @param {object} res - http response object
*/
static sendOkDataOnly(res, data) {
res.status(200).json(data)
}
/**
* Return a http response with status and data
* @param {object} res - http response object
* @param {object} data - data object
*/
static sendOkData(res, data) {
const ret = {
status: 'ok',
data: data
}
res.status(200).json(ret)
}
/**
* Return a http response with raw data
* @param {object} res - http response object
* @param {object} data - data object
*/
static sendRawData(res, data) {
res.status(200).send(data)
}
/**
* Return an error response
* @param {object} res - http response object
* @param {object} data - data object
*/
static sendError(res, data, errorCode) {
if (errorCode == null)
errorCode = 400
const ret = {
status: 'error',
error: data
}
res.status(errorCode).json(ret)
}
/*
* A middleware returning an authorization error response
* @param {string} err - error
* @param {object} req - http request object
* @param {object} res - http response object
* @param {function} next - callback function
*/
static sendAuthError(err, req, res, next) {
if (err) {
HttpServer.sendError(res, err, 401)
}
}
/**
* Express middleware returnsing a json response
* @param {object} req - http request object
* @param {object} res - http response object
* @param {function} next - next middleware
*/
static setJSONResponse(req, res, next) {
res.set('Content-Type', 'application/json')
next()
}
/**
* Express middleware adding cors header
* @param {object} req - http request object
* @param {object} res - http response object
* @param {function} next - next middleware
*/
static setCrossOrigin(req, res, next) {
res.set('Access-Control-Allow-Origin', '*')
res.set('Access-Control-Allow-Methods', 'GET,HEAD,POST,DELETE')
res.set('Access-Control-Allow-Headers', 'Content-Type,Authorization,Accept')
next()
}
/**
* Express middleware adding connection header
* @param {object} req - http request object
* @param {object} res - http response object
* @param {function} next - next middleware
*/
static setConnection(req, res, next) {
res.set('Connection', 'close')
next()
}
/**
* Express middleware logging url and methods called
* @param {object} req - http request object
* @param {object} res - http response object
* @param {function} next - next middleware
*/
static requestLogger(req, res, next) {
Logger.info(`HttpServer : ${req.method} ${req.url}`)
next()
}
}
/**
* Helmet Policy
*/
HttpServer.HELMET_POLICY = {
'contentSecurityPolicy' : {
'directives': {
'defaultSrc': ['"self"'],
'styleSrc' : ['"self"', '"unsafe-inline"'],
'img-src' : ['"self" data:']
},
'browserSniff': false,
'disableAndroid': true
},
'dnsPrefetchControl': true,
'frameguard': true,
'hidePoweredBy': true,
'hpkp': false,
'hsts': true,
'ieNoOpen': true,
'noCache': true,
'noSniff': true,
'referrerPolicy': true,
'xssFilter': true
}
module.exports = HttpServer