2018-06-06 03:35:19 +02:00
// load modules
2018-04-17 23:54:10 +02:00
const express = require ( 'express' ) ;
const bodyParser = require ( 'body-parser' ) ;
const expressHandlebars = require ( 'express-handlebars' ) ;
const helmet = require ( 'helmet' ) ;
const cookieSession = require ( 'cookie-session' ) ;
const http = require ( 'http' ) ;
const logger = require ( 'winston' ) ;
const Path = require ( 'path' ) ;
2018-09-28 05:56:10 +02:00
const httpContext = require ( 'express-http-context' ) ;
2018-06-06 03:35:19 +02:00
// load local modules
2018-09-03 01:48:35 +02:00
const db = require ( './models' ) ;
2018-10-24 10:43:30 +02:00
const requestLogger = require ( './middleware/requestLogger' ) ;
const createDatabaseIfNotExists = require ( './models/utils/createDatabaseIfNotExists' ) ;
2018-08-01 01:01:16 +02:00
const { getWalletBalance } = require ( './lbrynet/index' ) ;
2018-10-24 10:43:30 +02:00
const configureLogging = require ( './utils/configureLogging' ) ;
const configureSlack = require ( './utils/configureSlack' ) ;
2019-01-07 23:44:34 +01:00
const { setupBlockList } = require ( './utils/blockList' ) ;
2018-10-24 10:43:30 +02:00
const speechPassport = require ( './speechPassport' ) ;
const processTrending = require ( './utils/processTrending' ) ;
const {
logMetricsMiddleware ,
setRouteDataInContextMiddleware ,
} = require ( './middleware/logMetricsMiddleware' ) ;
2018-06-06 03:55:44 +02:00
2018-06-07 00:12:07 +02:00
const {
2019-01-07 23:44:34 +01:00
details : { port : PORT , blockListEndpoint } ,
2018-06-28 20:31:21 +02:00
startup : {
performChecks ,
performUpdates ,
} ,
2018-06-07 00:12:07 +02:00
} = require ( '@config/siteConfig' ) ;
2018-04-17 23:54:10 +02:00
2018-11-15 17:08:33 +01:00
const { sessionKey } = require ( '@private/authConfig.json' ) ;
2019-01-07 23:44:34 +01:00
// configure.js doesn't handle new keys in config.json files yet. Make sure it doens't break.
2019-01-14 07:27:23 +01:00
let finalBlockListEndpoint ;
2019-01-07 23:44:34 +01:00
2018-04-17 23:54:10 +02:00
function Server ( ) {
2018-06-06 21:01:11 +02:00
this . initialize = ( ) => {
// configure logging
configureLogging ( ) ;
// configure slack logging
configureSlack ( ) ;
} ;
2018-04-17 23:54:10 +02:00
this . createApp = ( ) => {
2018-06-06 21:01:11 +02:00
/* create app */
2018-04-17 23:54:10 +02:00
const app = express ( ) ;
2018-12-14 04:55:59 +01:00
if ( process . env . NODE _ENV === 'development' ) {
const webpack = require ( 'webpack' ) ;
const webpackDevMiddleware = require ( 'webpack-dev-middleware' ) ;
const webpackClientConfig = require ( '../webpack/webpack.client.config' ) ( null , { mode : 'development' } ) ;
const clientCompiler = webpack ( webpackClientConfig ) ;
app . use ( webpackDevMiddleware ( clientCompiler , {
publicPath : webpackClientConfig . output . publicPath ,
} ) ) ;
2018-12-14 18:17:28 +01:00
app . use ( require ( 'webpack-hot-middleware' ) ( clientCompiler ) ) ;
2018-12-14 04:55:59 +01:00
}
2018-04-17 23:54:10 +02:00
// trust the proxy to get ip address for us
app . enable ( 'trust proxy' ) ;
2018-10-18 19:05:01 +02:00
app . use ( ( req , res , next ) => {
2018-11-11 01:11:12 +01:00
if ( req . get ( 'User-Agent' ) === 'Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20120405 Firefox/14.0a1' ) {
2018-10-18 19:05:01 +02:00
res . status ( 403 ) . send ( '<h1>Forbidden</h1>If you are seeing this by mistake, please contact us using <a href="https://chat.lbry.io/">https://chat.lbry.io/</a>' ) ;
res . end ( ) ;
} else {
next ( ) ;
}
} ) ;
2018-04-17 23:54:10 +02:00
// set HTTP headers to protect against well-known web vulnerabilties
app . use ( helmet ( ) ) ;
2018-05-02 22:08:25 +02:00
2018-09-28 05:56:10 +02:00
// Support per-request http-context
app . use ( httpContext . middleware ) ;
2018-11-09 18:53:43 +01:00
// 'express.static' to serve static files from site/public directory
const sitePublicPath = Path . resolve ( process . cwd ( ) , 'site/public' ) ;
app . use ( express . static ( sitePublicPath ) ) ;
logger . info ( ` serving static files from site static path at ${ sitePublicPath } . ` ) ;
2018-04-17 23:54:10 +02:00
// 'express.static' to serve static files from public directory
2018-05-02 22:08:25 +02:00
const publicPath = Path . resolve ( process . cwd ( ) , 'public' ) ;
app . use ( express . static ( publicPath ) ) ;
logger . info ( ` serving static files from default static path at ${ publicPath } . ` ) ;
2018-04-17 23:54:10 +02:00
// 'body parser' for parsing application/json
app . use ( bodyParser . json ( ) ) ;
2018-05-02 22:08:25 +02:00
2018-04-17 23:54:10 +02:00
// 'body parser' for parsing application/x-www-form-urlencoded
app . use ( bodyParser . urlencoded ( { extended : true } ) ) ;
// add custom middleware (note: build out to accept dynamically use what is in server/middleware/
app . use ( requestLogger ) ;
// initialize passport
app . use ( cookieSession ( {
2018-08-01 01:43:08 +02:00
name : 'session' ,
keys : [ sessionKey ] ,
2018-04-17 23:54:10 +02:00
} ) ) ;
app . use ( speechPassport . initialize ( ) ) ;
app . use ( speechPassport . session ( ) ) ;
// configure handlebars & register it with express app
2018-10-11 07:50:04 +02:00
const viewsPath = Path . resolve ( process . cwd ( ) , 'server/views' ) ;
2018-07-03 03:22:06 +02:00
app . engine ( 'handlebars' , expressHandlebars ( {
2018-08-01 01:43:08 +02:00
async : false ,
dataType : 'text' ,
2018-04-17 23:54:10 +02:00
defaultLayout : 'embed' ,
2018-08-01 01:43:08 +02:00
partialsDir : Path . join ( viewsPath , '/partials' ) ,
layoutsDir : Path . join ( viewsPath , '/layouts' ) ,
2018-07-03 03:22:06 +02:00
} ) ) ;
app . set ( 'views' , viewsPath ) ;
2018-04-17 23:54:10 +02:00
app . set ( 'view engine' , 'handlebars' ) ;
// set the routes on the app
2018-09-28 05:56:10 +02:00
const routes = require ( './routes' ) ;
Object . keys ( routes ) . map ( ( routePath ) => {
let routeData = routes [ routePath ] ;
let routeMethod = routeData . hasOwnProperty ( 'method' ) ? routeData . method : 'get' ;
let controllers = Array . isArray ( routeData . controller ) ? routeData . controller : [ routeData . controller ] ;
2018-10-09 02:02:05 +02:00
app [ routeMethod ] (
routePath ,
logMetricsMiddleware ,
setRouteDataInContextMiddleware ( routePath , routeData ) ,
... controllers ,
) ;
2018-09-28 05:56:10 +02:00
} ) ;
2018-04-17 23:54:10 +02:00
this . app = app ;
} ;
2018-06-06 21:01:11 +02:00
this . createServer = ( ) => {
/* create server */
2018-04-17 23:54:10 +02:00
this . server = http . Server ( this . app ) ;
} ;
2018-06-28 20:19:24 +02:00
this . startServerListening = ( ) => {
logger . info ( ` Starting server on ${ PORT } ... ` ) ;
return new Promise ( ( resolve , reject ) => {
this . server . listen ( PORT , ( ) => {
logger . info ( ` Server is listening on PORT ${ PORT } ` ) ;
resolve ( ) ;
2018-08-01 01:43:08 +02:00
} ) ;
2018-06-28 20:19:24 +02:00
} ) ;
} ;
2018-06-06 21:01:11 +02:00
this . syncDatabase = ( ) => {
2018-06-28 20:19:24 +02:00
logger . info ( ` Syncing database... ` ) ;
2018-06-06 21:01:11 +02:00
return createDatabaseIfNotExists ( )
2018-05-17 23:42:58 +02:00
. then ( ( ) => {
2018-05-18 04:01:35 +02:00
db . sequelize . sync ( ) ;
2018-08-01 01:43:08 +02:00
} ) ;
2018-06-06 21:01:11 +02:00
} ;
2018-06-28 20:31:21 +02:00
this . performChecks = ( ) => {
if ( ! performChecks ) {
return ;
}
logger . info ( ` Performing checks... ` ) ;
2018-06-28 20:19:24 +02:00
return Promise . all ( [
getWalletBalance ( ) ,
2018-06-28 20:31:21 +02:00
] )
. then ( ( [ walletBalance ] ) => {
logger . info ( 'Starting LBC balance:' , walletBalance ) ;
2018-08-01 01:43:08 +02:00
} ) ;
2018-06-28 20:31:21 +02:00
} ;
2019-01-07 23:44:34 +01:00
2018-06-28 20:31:21 +02:00
this . performUpdates = ( ) => {
if ( ! performUpdates ) {
return ;
}
2019-01-07 23:44:34 +01:00
if ( blockListEndpoint ) {
2019-01-14 07:27:23 +01:00
finalBlockListEndpoint = blockListEndpoint ;
2019-01-07 23:44:34 +01:00
} else if ( ! blockListEndpoint ) {
if ( typeof ( blockListEndpoint ) !== 'string' ) {
logger . warn ( 'blockListEndpoint is null due to outdated siteConfig file. \n' +
'Continuing with default LBRY blocklist api endpoint. \n ' +
2019-01-14 07:27:23 +01:00
'(Specify /"blockListEndpoint" : ""/ to disable.' ) ;
finalBlockListEndpoint = 'https://api.lbry.io/file/list_blocked' ;
2019-01-07 23:44:34 +01:00
}
}
2018-06-28 20:31:21 +02:00
logger . info ( ` Peforming updates... ` ) ;
2019-01-14 07:27:23 +01:00
if ( ! finalBlockListEndpoint ) {
logger . info ( 'Configured for no Block List' ) ;
db . Tor . refreshTable ( ) . then ( ( updatedTorList ) => {
2018-06-28 20:31:21 +02:00
logger . info ( 'Tor list updated, length:' , updatedTorList . length ) ;
2018-08-01 01:43:08 +02:00
} ) ;
2019-01-07 23:44:34 +01:00
} else {
return Promise . all ( [
2019-01-14 07:27:23 +01:00
db . Blocked . refreshTable ( finalBlockListEndpoint ) ,
2019-01-07 23:44:34 +01:00
db . Tor . refreshTable ( ) ] )
. then ( ( [ updatedBlockedList , updatedTorList ] ) => {
logger . info ( 'Blocked list updated, length:' , updatedBlockedList . length ) ;
logger . info ( 'Tor list updated, length:' , updatedTorList . length ) ;
2019-01-14 07:27:23 +01:00
} ) ;
2019-01-07 23:44:34 +01:00
}
2018-06-28 20:19:24 +02:00
} ;
2018-06-06 21:01:11 +02:00
this . start = ( ) => {
this . initialize ( ) ;
this . createApp ( ) ;
this . createServer ( ) ;
2018-06-28 19:39:46 +02:00
this . syncDatabase ( )
. then ( ( ) => {
2018-06-28 20:19:24 +02:00
return this . startServerListening ( ) ;
2018-04-17 23:54:10 +02:00
} )
2018-06-28 19:39:46 +02:00
. then ( ( ) => {
2018-06-28 20:31:21 +02:00
return Promise . all ( [
this . performChecks ( ) ,
this . performUpdates ( ) ,
2018-08-01 01:43:08 +02:00
] ) ;
2018-06-28 19:39:46 +02:00
} )
2019-01-07 23:44:34 +01:00
. then ( ( ) => {
return setupBlockList ( ) ;
} )
2018-06-28 20:19:24 +02:00
. then ( ( ) => {
2018-06-28 20:31:21 +02:00
logger . info ( 'Spee.ch startup is complete' ) ;
2018-10-24 10:43:30 +02:00
2018-11-11 01:11:12 +01:00
setInterval ( processTrending , 30 * 60000 ) ; // 30 minutes
2018-06-28 19:39:46 +02:00
} )
2018-05-18 03:11:22 +02:00
. catch ( error => {
if ( error . code === 'ECONNREFUSED' ) {
2018-08-01 01:43:08 +02:00
return logger . error ( 'Connection refused. The daemon may not be running.' ) ;
2018-06-28 20:19:24 +02:00
} else if ( error . code === 'EADDRINUSE' ) {
return logger . error ( 'Server could not start listening. The port is already in use.' ) ;
2018-05-18 03:11:22 +02:00
} else if ( error . message ) {
logger . error ( error . message ) ;
}
logger . error ( error ) ;
2018-04-17 23:54:10 +02:00
} ) ;
} ;
2018-06-06 21:01:11 +02:00
}
2018-04-17 23:54:10 +02:00
module . exports = Server ;