-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
server.js
122 lines (105 loc) · 3.81 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import Express from 'express';
import React from 'react';
import ReactDOM from 'react-dom/server';
import config from './config';
import favicon from 'serve-favicon';
import compression from 'compression';
import httpProxy from 'http-proxy';
import path from 'path';
import createStore from './redux/create';
import ApiClient from './helpers/ApiClient';
import Html from './helpers/Html';
import PrettyError from 'pretty-error';
import http from 'http';
import { match } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import { ReduxAsyncConnect, loadOnServer } from 'redux-async-connect';
import createHistory from 'react-router/lib/createMemoryHistory';
import {Provider} from 'react-redux';
import getRoutes from './routes';
const targetUrl = 'http://' + config.apiHost + ':' + config.apiPort;
const pretty = new PrettyError();
const app = new Express();
const server = new http.Server(app);
const proxy = httpProxy.createProxyServer({
target: targetUrl,
ws: true
});
app.use(compression());
app.use(favicon(path.join(__dirname, '..', 'static', 'favicon.ico')));
app.use(Express.static(path.join(__dirname, '..', 'static')));
// Proxy to API server
app.use('/api', (req, res) => {
proxy.web(req, res, {target: targetUrl});
});
app.use('/ws', (req, res) => {
proxy.web(req, res, {target: targetUrl + '/ws'});
});
server.on('upgrade', (req, socket, head) => {
proxy.ws(req, socket, head);
});
// added the error handling to avoid https://github.com/nodejitsu/node-http-proxy/issues/527
proxy.on('error', (error, req, res) => {
let json;
if (error.code !== 'ECONNRESET') {
console.error('proxy error', error);
}
if (!res.headersSent) {
res.writeHead(500, {'content-type': 'application/json'});
}
json = {error: 'proxy_error', reason: error.message};
res.end(JSON.stringify(json));
});
app.use((req, res) => {
if (__DEVELOPMENT__) {
// Do not cache webpack stats: the script file would change since
// hot module replacement is enabled in the development env
webpackIsomorphicTools.refresh();
}
const client = new ApiClient(req);
const memoryHistory = createHistory(req.originalUrl);
const store = createStore(memoryHistory, client);
const history = syncHistoryWithStore(memoryHistory, store);
function hydrateOnClient() {
res.send('<!doctype html>\n' +
ReactDOM.renderToString(<Html assets={webpackIsomorphicTools.assets()} store={store}/>));
}
if (__DISABLE_SSR__) {
hydrateOnClient();
return;
}
match({ history, routes: getRoutes(store), location: req.originalUrl }, (error, redirectLocation, renderProps) => {
if (redirectLocation) {
res.redirect(redirectLocation.pathname + redirectLocation.search);
} else if (error) {
console.error('ROUTER ERROR:', pretty.render(error));
res.status(500);
hydrateOnClient();
} else if (renderProps) {
loadOnServer({...renderProps, store, helpers: {client}}).then(() => {
const component = (
<Provider store={store} key="provider">
<ReduxAsyncConnect {...renderProps} />
</Provider>
);
res.status(200);
global.navigator = {userAgent: req.headers['user-agent']};
res.send('<!doctype html>\n' +
ReactDOM.renderToString(<Html assets={webpackIsomorphicTools.assets()} component={component} store={store}/>));
});
} else {
res.status(404).send('Not found');
}
});
});
if (config.port) {
server.listen(config.port, (err) => {
if (err) {
console.error(err);
}
console.info('----\n==> ✅ %s is running, talking to API server on %s.', config.app.title, config.apiPort);
console.info('==> 💻 Open http://%s:%s in a browser to view the app.', config.host, config.port);
});
} else {
console.error('==> ERROR: No PORT environment variable has been specified');
}