2016-05-05 04:06:52 +08:00
import * as _express from "express" ;
import * as _session from "express-session" ;
import * as _bodyParser from "body-parser" ;
import * as _http from "http" ;
2017-06-04 21:25:08 +08:00
import * as winston from "winston" ;
import * as expressWinston from "express-winston" ;
2016-03-19 04:36:58 +08:00
import { PublicRouter } from "./routes/PublicRouter" ;
import { UserRouter } from "./routes/UserRouter" ;
2016-03-20 00:31:42 +08:00
import { GalleryRouter } from "./routes/GalleryRouter" ;
2016-05-05 04:06:52 +08:00
import { AdminRouter } from "./routes/AdminRouter" ;
2016-03-26 18:19:10 +08:00
import { ErrorRouter } from "./routes/ErrorRouter" ;
import { SharingRouter } from "./routes/SharingRouter" ;
2016-04-22 19:23:44 +08:00
import { ObjectManagerRepository } from "./model/ObjectManagerRepository" ;
2017-06-04 04:35:47 +08:00
import { Logger } from "./Logger" ;
2017-06-04 21:25:08 +08:00
import { Config } from "../common/config/private/Config" ;
import { DatabaseType } from "../common/config/private/IPrivateConfig" ;
2016-03-12 19:53:19 +08:00
2017-06-04 04:35:47 +08:00
const LOG_TAG = "[server]" ;
2016-03-12 21:57:22 +08:00
export class Server {
2016-03-12 19:53:19 +08:00
2016-12-27 06:36:38 +08:00
private debug : any ;
private app : any ;
private server : any ;
2016-03-12 19:53:19 +08:00
2016-05-05 04:06:52 +08:00
constructor ( ) {
2017-06-04 21:25:08 +08:00
this . init ( ) ;
}
async init() {
2017-06-04 04:35:47 +08:00
Logger . info ( LOG_TAG , "config:" ) ;
Logger . info ( LOG_TAG , JSON . stringify ( Config , null , '\t' ) ) ;
2016-03-12 19:53:19 +08:00
2016-03-12 21:57:22 +08:00
this . app = _express ( ) ;
2016-03-12 19:53:19 +08:00
2017-06-04 21:25:08 +08:00
this . app . use ( expressWinston . logger ( {
transports : [
new winston . transports . Console ( {
level : 'silly' ,
json : false ,
colorize : true ,
timestamp : function ( ) {
return ( new Date ( ) ) . toLocaleString ( ) ;
} ,
formatter : ( options ) = > {
// Return string will be passed to logger.
return options . timestamp ( ) + '[' + winston [ 'config' ] [ 'colorize' ] ( options . level , options . level . toUpperCase ( ) ) + '] ' +
( undefined !== options . message ? options . message : '' ) +
( options . meta && Object . keys ( options . meta ) . length ? '\n\t' + JSON . stringify ( options . meta ) : '' ) ;
} ,
debugStdout : true
} )
] ,
meta : false , // optional: control whether you want to log the meta data about the request (default to true)
msg : "HTTP {{req.method}} {{req.url}}" , // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
expressFormat : true , // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
colorize : true , // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
level : ( req ) = > {
if ( req . url . indexOf ( "/api/" ) !== - 1 ) {
return "verbose" ;
}
return req . url . indexOf ( "node_modules" ) !== - 1 ? "silly" : "debug"
}
} ) ) ;
2016-04-10 00:06:29 +08:00
2017-06-04 21:25:08 +08:00
this . app . set ( 'view engine' , 'ejs' ) ;
2016-03-12 19:53:19 +08:00
2016-05-12 17:00:46 +08:00
2016-03-19 04:36:58 +08:00
/ * *
* Session above all
* /
this . app . use ( _session ( {
2016-05-05 04:06:52 +08:00
name : "pigallery2-session" ,
2016-03-21 03:06:14 +08:00
secret : 'PiGallery2 secret' ,
2016-03-19 04:36:58 +08:00
cookie : {
2016-05-05 04:06:52 +08:00
maxAge : 60000 * 10 ,
2016-03-21 03:06:14 +08:00
httpOnly : false
2016-03-19 04:36:58 +08:00
} ,
resave : true ,
saveUninitialized : false
} ) ) ;
2016-03-20 23:54:30 +08:00
/ * *
* Parse parameters in POST
* /
// for parsing application/json
this . app . use ( _bodyParser . json ( ) ) ;
2016-03-27 02:24:12 +08:00
2017-06-04 04:35:47 +08:00
if ( Config . Server . database . type == DatabaseType . mysql ) {
2017-06-04 21:25:08 +08:00
try {
await ObjectManagerRepository . InitMySQLManagers ( ) ;
} catch ( err ) {
Logger . warn ( LOG_TAG , "[MYSQL error]" , err ) ;
Logger . warn ( LOG_TAG , "Error during initializing mysql falling back to memory DB" ) ;
2017-06-04 04:35:47 +08:00
Config . setDatabaseType ( DatabaseType . memory ) ;
2017-06-04 21:25:08 +08:00
await ObjectManagerRepository . InitMemoryManagers ( ) ;
}
2017-06-04 04:35:47 +08:00
} else {
2017-06-04 21:25:08 +08:00
await ObjectManagerRepository . InitMemoryManagers ( ) ;
2017-06-04 04:35:47 +08:00
}
2016-03-19 04:36:58 +08:00
2017-05-28 18:33:18 +08:00
if ( Config . Server . thumbnail . hardwareAcceleration == true ) {
try {
2017-06-04 21:25:08 +08:00
const sharp = require ( "sharp" ) ;
sharp ( ) ;
2017-05-28 18:33:18 +08:00
} catch ( err ) {
2017-06-04 21:25:08 +08:00
Logger . warn ( LOG_TAG , "[Thumbnail hardware acceleration] sharp module error: " , err ) ;
2017-06-04 04:35:47 +08:00
Logger . warn ( LOG_TAG , "Thumbnail hardware acceleration is not possible." +
2017-05-28 18:33:18 +08:00
" 'Sharp' node module is not found." +
" Falling back to JS based thumbnail generation" ) ;
Config . Server . thumbnail . hardwareAcceleration = false ;
}
}
2017-06-04 21:25:08 +08:00
PublicRouter . route ( this . app ) ;
2016-05-05 04:06:52 +08:00
2017-06-04 21:25:08 +08:00
UserRouter . route ( this . app ) ;
GalleryRouter . route ( this . app ) ;
SharingRouter . route ( this . app ) ;
AdminRouter . route ( this . app ) ;
2016-03-13 01:11:19 +08:00
2017-06-04 21:25:08 +08:00
ErrorRouter . route ( this . app ) ;
2016-03-12 19:53:19 +08:00
2016-05-01 16:50:17 +08:00
// Get PORT from environment and store in Express.
2016-05-11 03:33:58 +08:00
this . app . set ( 'port' , Config . Server . port ) ;
2016-03-12 19:53:19 +08:00
2016-03-12 21:57:22 +08:00
// Create HTTP server.
this . server = _http . createServer ( this . app ) ;
2016-03-12 19:53:19 +08:00
2016-05-01 16:50:17 +08:00
//Listen on provided PORT, on all network interfaces.
2016-05-11 03:33:58 +08:00
this . server . listen ( Config . Server . port ) ;
2016-03-12 21:57:22 +08:00
this . server . on ( 'error' , this . onError ) ;
this . server . on ( 'listening' , this . onListening ) ;
2016-03-12 19:53:19 +08:00
}
2016-03-12 21:57:22 +08:00
/ * *
* Event listener for HTTP server "error" event .
* /
2016-12-27 06:36:38 +08:00
private onError = ( error : any ) = > {
2016-03-12 21:57:22 +08:00
if ( error . syscall !== 'listen' ) {
2016-03-12 19:53:19 +08:00
throw error ;
2016-03-12 21:57:22 +08:00
}
2016-12-28 19:30:26 +08:00
const bind = typeof Config . Server . port === 'string'
2016-05-11 03:33:58 +08:00
? 'Pipe ' + Config . Server . port
: 'Port ' + Config . Server . port ;
2016-03-12 21:57:22 +08:00
2016-03-26 18:19:10 +08:00
// handle specific listen error with friendly messages
2016-03-12 21:57:22 +08:00
switch ( error . code ) {
case 'EACCES' :
2017-06-04 04:35:47 +08:00
Logger . error ( LOG_TAG , bind + ' requires elevated privileges' ) ;
2016-03-12 21:57:22 +08:00
process . exit ( 1 ) ;
break ;
case 'EADDRINUSE' :
2017-06-04 04:35:47 +08:00
Logger . error ( LOG_TAG , bind + ' is already in use' ) ;
2016-03-12 21:57:22 +08:00
process . exit ( 1 ) ;
break ;
default :
throw error ;
}
} ;
/ * *
* Event listener for HTTP server "listening" event .
* /
private onListening = ( ) = > {
2016-12-28 19:30:26 +08:00
let addr = this . server . address ( ) ;
const bind = typeof addr === 'string'
2016-03-12 21:57:22 +08:00
? 'pipe ' + addr
: 'port ' + addr . port ;
2017-06-04 21:25:08 +08:00
Logger . info ( LOG_TAG , 'Listening on ' + bind ) ;
2016-03-12 21:57:22 +08:00
} ;
2016-03-12 19:53:19 +08:00
}
2016-05-05 04:06:52 +08:00
if ( process . env . DEBUG ) {
2017-06-04 04:35:47 +08:00
Logger . debug ( LOG_TAG , "Running in DEBUG mode" ) ;
2016-03-12 19:53:19 +08:00
}
2016-03-12 21:57:22 +08:00
new Server ( ) ;