UNPKG

3.88 kBJavaScriptView Raw
1var express = require('express');
2var fs = require('fs');
3var cors = require('cors');
4var path = require('path');
5var bodyParser = require('body-parser');
6var urlParse = require('url').parse;
7var _ = require('lodash');
8var http = require('http');
9var https = require('https');
10var glob = require('glob');
11var mime = require('mime');
12var crypto = require('crypto');
13var debug = require('debug')('4front:cli:sandbox-server');
14var api = require('./api');
15var log = require('./log');
16var helper = require('./helper');
17var tinylr = require('tiny-lr');
18var onFinished = require('on-finished');
19
20require('simple-errors');
21
22
23// The localhost express server that works in tandem with the sanbox
24// environment running in the 4front cloud.
25
26module.exports = function(program) {
27 log.debug("Creating development express app");
28 var localhost = express();
29
30 // If liveReload is true, configure the middleware
31 if (program.liveReload) {
32 localhost.use(tinylr.middleware({
33 app: localhost,
34 liveCSS: true,
35 liveJs: true,
36 liveImg: true
37 }));
38 }
39
40 localhost.use(function(req, res, next) {
41 log.debug("Request for %s", req.path);
42
43 onFinished(res, function() {
44 // Write each request to the log in a format that emulates NPM
45 log({
46 process: '4front',
47 status: res.statusCode,
48 color: res.statusCode === 200 ? 'green' : 'magenta',
49 message: "Serving " + req.path
50 });
51 });
52
53 next();
54 });
55
56 // Serve node_modules and bower_components from the root of the app
57 // regardless of the value of program.baseDir
58 localhost.use('/node_modules', express.static(path.join(program.cwd, 'node_modules'), {
59 index: false
60 }));
61
62 localhost.use('/bower_components', express.static(path.join(program.cwd, 'bower_components'), {
63 index: false
64 }));
65
66 localhost.use(cors());
67
68 localhost.use('/static', express.static(path.join(__dirname, '../static')));
69
70 localhost.use(express.static(program.baseDir, {
71 index: false
72 }));
73
74 // Redirects from the 4front sandbox cloud server
75 localhost.get(/sandbox\/(.*)$/ , function(req, res, next) {
76 log.info("sandbox request for %s with hash %s", req.params[0], req.query.hash || 'none');
77
78 var returnUrl = urlParse(req.query.return);
79 if (!returnUrl.host)
80 return next(Error.http(400, "No valid URL in the return query"));
81
82 var pagePath = req.params[0];
83 var fullPath = path.join(program.baseDir, pagePath);
84
85 fs.exists(fullPath, function(exists) {
86 if (!exists)
87 return next(Error.http(404, "Page " + fullPath + " not found"));
88
89 // Get the hash of the file
90 // TODO: What if the file has references to other files internally,
91 // for example liquid templates. Would it be possible to scan through the
92 // document and find references to other files?
93 helper.fileHash(fullPath, function(err, hash) {
94 if (err) return next(err);
95
96 // If the server already has the latest version, just redirect
97 // back to the server hosted version.
98 if (hash === req.query.hash) {
99 debug("hash for page %s has not changed", pagePath);
100 return res.redirect(req.query.return);
101 }
102
103 // Pipe the local version up to the sandbox server
104 var requestOptions = {
105 method: 'post',
106 path: '/dev/' + program.virtualApp.appId + '/upload/' + pagePath,
107 json: false,
108 headers: {}
109 };
110
111 requestOptions.headers['File-Hash'] = hash;
112
113 debug("uploading file %s to %s with File-Hash header of %s",
114 pagePath, requestOptions.path, hash);
115
116 fs.createReadStream(fullPath)
117 .pipe(api(program, requestOptions, function(err) {
118 if (err) return next(err);
119
120 res.redirect(req.query.return);
121 }));
122 });
123 });
124 });
125
126 // Anything not served by the static middleware is a 404
127 localhost.get('/*', function(req, res, next) {
128 next(Error.http(404, "Path " + req.originalUrl + " not found"));
129 });
130
131 localhost.use(require('./middleware').error);
132
133 return localhost;
134};