2017-02-09 22:55:56 +00:00
const compression = require ( "compression" ) ;
2017-02-10 11:12:47 +00:00
const ejs = require ( "ejs" ) ;
2017-02-09 22:55:56 +00:00
const express = require ( "express" ) ;
2017-02-13 11:39:17 +00:00
const fs = require ( "fs" ) ;
2017-02-09 22:55:56 +00:00
const http = require ( "http" ) ;
const path = require ( "path" ) ;
const Promise = require ( "promise" ) ;
const config = require ( "../config" ) ;
2017-02-10 11:12:47 +00:00
const database = require ( "./database/database" ) ;
2017-02-10 11:41:14 +00:00
const gpx = require ( "./gpx" ) ;
2017-02-10 11:12:47 +00:00
const utils = require ( "./utils" ) ;
2017-02-09 22:55:56 +00:00
2017-02-21 23:55:11 +00:00
const frontendPath = path . dirname ( require . resolve ( "facilmap-frontend/package.json" ) ) ; // Do not resolve main property
if ( process . env . FM _DEV )
process . chdir ( frontendPath ) ; // To make sure that webpack finds all the loaders
2017-02-09 22:55:56 +00:00
const webserver = module . exports = {
2017-02-10 11:12:47 +00:00
init ( database ) {
const staticMiddleware = process . env . FM _DEV
2017-02-21 23:55:11 +00:00
? require ( "webpack-dev-middleware" ) ( require ( "webpack" ) ( require ( "facilmap-frontend/webpack.config" ) ) , { // require the stuff here so that it doesn't fail if devDependencies are not installed
2017-02-10 11:12:47 +00:00
publicPath : "/"
} )
: express . static ( frontendPath + "/build/" ) ;
const padMiddleware = function ( req , res , next ) {
utils . promiseAuto ( {
template : ( ) => {
2017-02-13 11:39:17 +00:00
if ( process . env . FM _DEV ) {
let intercept = utils . interceptWriteStream ( res ) ;
req . url = req . originalUrl = "/index.ejs" ;
staticMiddleware ( req , res , next ) ;
return intercept ;
} else {
// We don't want express.static's ETag handling, as it sometimes returns an empty template,
// so we have to read it directly from the file system
2017-02-10 11:12:47 +00:00
2017-02-13 11:39:17 +00:00
return Promise . denodeify ( fs . readFile ) ( ` ${ frontendPath } /build/index.ejs ` , "utf8" ) ;
}
2017-02-10 11:12:47 +00:00
} ,
padData : ( ) => {
if ( req . params && req . params . padId ) {
return database . getPadData ( req . params . padId ) . then ( ( padData ) => {
// We only look up by read ID. At the moment, we only need the data for the search engine
// meta tags, and those should be only enabled in the read-only version anyways.
if ( ! padData )
throw new Error ( ) ;
return padData ;
} ) . catch ( ( ) => {
// Error will be handled on the client side when it tries to fetch the pad data
return {
searchEngines : false ,
description : ""
} ;
} ) ;
}
} ,
render : ( template , padData ) => {
res . type ( "html" ) ;
res . send ( ejs . render ( template , {
padData : padData
} ) ) ;
}
} ) . catch ( next ) ;
} ;
2017-02-09 22:55:56 +00:00
let app = express ( ) ;
app . use ( compression ( ) ) ;
app . get ( "/bundle-:hash.js" , function ( req , res , next ) {
res . setHeader ( 'Cache-Control' , 'public, max-age=31557600' ) ; // one year
next ( ) ;
} ) ;
2017-02-10 11:12:47 +00:00
app . get ( "/" , padMiddleware ) ;
app . get ( "/index.ejs" , padMiddleware ) ;
2017-02-09 22:55:56 +00:00
2017-02-10 11:12:47 +00:00
app . use ( staticMiddleware ) ;
2017-02-09 22:55:56 +00:00
2017-02-10 11:12:47 +00:00
// If no file with this name has been found, we render a pad
app . get ( "/:padId" , padMiddleware ) ;
2017-02-09 22:55:56 +00:00
2017-02-10 11:41:14 +00:00
app . get ( "/:padId/gpx" , function ( req , res , next ) {
utils . promiseAuto ( {
padData : database . getPadDataByAnyId ( req . params . padId ) . then ( ( padData ) => {
if ( ! padData )
throw new Error ( ` Map with ID ${ req . params . padId } could not be found. ` ) ;
return padData ;
} ) ,
gpx : ( padData ) => {
return gpx . exportGpx ( database , padData ? padData . id : req . params . padId , req . query . useTracks == "1" ) ;
} ,
response : ( padData , gpx ) => {
res . set ( "Content-type" , "application/gpx+xml" ) ;
res . attachment ( padData . name . replace ( /[\\\/:*?"<>|]+/g , '_' ) + ".gpx" ) ;
res . send ( gpx ) ;
}
} ) . catch ( next ) ;
} ) ;
2017-02-09 22:55:56 +00:00
let server = http . createServer ( app ) ;
return Promise . denodeify ( server . listen . bind ( server ) ) ( config . port , config . host ) . then ( ( ) => server ) ;
}
} ;