facilmap/server/webserver.js

111 wiersze
3.4 KiB
JavaScript
Czysty Zwykły widok Historia

2017-02-09 22:55:56 +00:00
const compression = require("compression");
const ejs = require("ejs");
2017-02-09 22:55:56 +00:00
const express = require("express");
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 database = require("./database/database");
2017-02-10 11:41:14 +00:00
const gpx = require("./gpx");
const utils = require("./utils");
2017-02-09 22:55:56 +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-22 15:25:46 +00:00
init(database, port, host) {
const staticMiddleware = process.env.FM_DEV
? 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
publicPath: "/"
})
: express.static(frontendPath + "/build/");
const padMiddleware = function(req, res, next) {
utils.promiseAuto({
template: () => {
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
return Promise.denodeify(fs.readFile)(`${frontendPath}/build/index.ejs`, "utf8");
}
},
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();
});
app.get("/", padMiddleware);
app.get("/index.ejs", padMiddleware);
2017-02-09 22:55:56 +00:00
app.use(staticMiddleware);
2017-02-09 22:55:56 +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);
2017-02-22 15:25:46 +00:00
return Promise.denodeify(server.listen.bind(server))(port, host).then(() => server);
2017-02-09 22:55:56 +00:00
}
};