-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathserver.ts
More file actions
122 lines (107 loc) · 4.15 KB
/
Copy pathserver.ts
File metadata and controls
122 lines (107 loc) · 4.15 KB
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 * as Sentry from '@sentry/node';
import { raw } from 'body-parser';
import cookieParser from 'cookie-parser';
import type { NextFunction, Request, RequestHandler, Response } from 'express';
import { default as express } from 'express';
import helmet from 'helmet';
import { MAX_FILE_ATTACHMENT_SIZE_KB } from '../shared/fileUploadUtils';
import { conf } from './config';
import { log } from './log';
import { getConfig } from './oktaConfig';
import * as routes from './routes';
const port = 9233;
const server = express();
const oktaConfig = await getConfig();
declare let WEBPACK_BUILD: string;
if (conf.SERVER_DSN) {
Sentry.init({
dsn: conf.SERVER_DSN,
release: WEBPACK_BUILD || 'local',
environment: conf.DOMAIN,
});
server.use(
Sentry.Handlers.requestHandler({
ip: false,
user: false,
request: ['method', 'query_string', 'url'], // this list is explicit, to avoid sending cookies
}),
);
}
if (conf.DOMAIN === 'thegulocal.com') {
// tslint:disable-next-line:no-object-mutation
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}
server.use(helmet());
server.use(function (_: Request, res: Response, next: NextFunction) {
res.set({
'Report-To':
'{ "group": "csp-endpoint", "endpoints": [ { "url": "/csp-audit-report-endpoint" } ] }',
'Content-Security-Policy-Report-Only':
'report-uri /csp-audit-report-endpoint; report-to csp-endpoint; default-src https:',
});
next();
});
const serveStaticAssets: RequestHandler = express.static(__dirname + '/static');
/** static asses are cached by fastly */
server.use('/static', serveStaticAssets);
/**
* WARNING: Because manage-fronted manages personal data make sure to prevent caching
* on both CDN (Fastly) and browsers. This Cache-Control header below is VERY IMPORTANT
* so mind removing or it! Without it personal data would likely be served to wrong user.
* In particular mind the endpoints that proxy to APIs such as IDAPI or MDAPI.
*
* This middleware has no mount path so it executes for all routes that follow this call.
* To enable caching for a route that requires it register it above this middleware, see /static
* route as example, or override headers via Response arguments for a particular route later one.
* https://stackoverflow.com/a/31661931
*
* There exists an additional safety net as a VCL condition in Fastly which should force a
* PASS (do not cache) on sensitive routes. See https://github.com/guardian/manage-frontend/wiki/Fastly-&-Caching
*/
const disableCache = (_: Request, res: Response, next: NextFunction) => {
res.header(
'Cache-Control',
'private, no-cache, no-store, must-revalidate, max-age=0',
);
res.header('Access-Control-Allow-Origin', '*.' + conf.DOMAIN);
next();
};
server.use(disableCache);
/**
* Cookies and body parsing
* ------------------------
* We don't parse the body of JSON requests that are coming into the server from
* the client using express.json() because MMA is essentially a proxy and is
* usually not interested in the body of the request. One of the exceptions is
* POST /aapi/avatar, which extracts file data from a JSON payload and reformats
* it. This is handled separately directly in the route handler.
*
* WARNING: A lot of the routes _rely_ on the JSON body not being parsed at the
* server level, so they don't stringify the body before sending it to
* downstream APIs. For this reason, think and test carefully before adding a
* global body parser to the server!
*/
server.use(cookieParser(oktaConfig.cookieSecret));
server.use(
raw({
type: '*/*',
limit: `${MAX_FILE_ATTACHMENT_SIZE_KB + 100}kb`,
}),
); // parses all bodys to a raw 'Buffer'
server.use(routes.core);
server.use('/oauth', routes.oauth);
server.use('/profile/', routes.profile);
server.use('/api/', routes.api);
server.use('/idapi', routes.idapi);
server.use('/mpapi', routes.mpapi);
server.use('/aapi', routes.aapi);
server.use(routes.productsProvider('/api/'));
// Help Centre
server.use('/help-centre', routes.helpcentre);
// ALL OTHER ENDPOINTS CAN BE HANDLED BY MMA CLIENT SIDE REACT ROUTING
server.use(routes.frontend);
if (conf.SERVER_DSN) {
server.use(Sentry.Handlers.errorHandler());
}
server.listen(port);
log.info(`Serving at http://localhost:${port}`);