-
-
Notifications
You must be signed in to change notification settings - Fork 49
/
middleware.js
153 lines (129 loc) · 4.08 KB
/
middleware.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
Copyright © 2018 Andrew Powell
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of this Source Code Form.
*/
const convert = require('koa-connect');
const historyApiFallback = require('connect-history-api-fallback');
const koaCompress = require('koa-compress');
const koaStatic = require('koa-static');
const onetime = require('onetime');
const { createProxyMiddleware } = require('http-proxy-middleware');
const { middleware: wsMiddleware } = require('./ws');
let staticPaths = [];
const render404 = (ctx) => {
const faqUrl =
'https://github.com/shellscape/webpack-plugin-serve/blob/master/.github/FAQ.md#what-does-the-not-found--404-error-mean';
const body = `<h1>Not Found / 404</h1>
<p>
You may be seeing this error due to misconfigured options.<br/>
Please see <a href="${faqUrl}">this FAQ question</a> for information on possible causes and remedies.
</p>
<h2>Static Paths</h2>
<code>${staticPaths.join('</code><code>')}</code>`;
const css = `<style>
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');
*, html {
font-size: 10px;
margin: 0;
}
body {
background: #282d35;
color: #fff;
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
padding: 2rem;
}
h1 {
font-size: 5rem;
padding-bottom: 2rem;
}
p {
color: #eee;
font-size: 1.6rem;
padding: 1rem 0 3rem 0;
}
a, a:visited, a:hover {
color: #ffbd2e;
font-size: 1.6rem;
text-decoration: none;
}
h2 {
color: #eee;
font-size: 1.5rem;
padding: 1rem 0;
}
code {
color: #eee;
font-size: 1.4rem;
padding: 0.4rem 1rem;
}
</style>`;
const html = `<!doctype><html><head>${css}</head><body>${body}</body></html>`;
ctx.body = html; // eslint-disable-line no-param-reassign
ctx.status = 404; // eslint-disable-line no-param-reassign
};
const getBuiltins = (app, options) => {
const compress = (opts) => {
// only enable compress middleware if the user has explictly enabled it
if (opts || options.compress) {
app.use(koaCompress(opts || options.compress));
}
};
const four0four = (fn = () => {}) => {
app.use(async (ctx, next) => {
await next();
if (ctx.status === 404) {
render404(ctx);
fn(ctx);
}
});
};
const headers = (reqHeaders) => {
const headrs = reqHeaders || (options.headers || {});
app.use(async (ctx, next) => {
await next();
for (const headr of Object.keys(headrs)) {
ctx.set(headr, headrs[headr]);
}
});
};
const historyFallback = () => {
if (options.historyFallback) {
// https://github.com/shellscape/webpack-plugin-serve/issues/94
// When using Firefox, the browser sends an accept header for /wps when using connect-history-api-fallback
app.use(async (ctx, next) => {
if (ctx.path.match(/^\/wps/)) {
const { accept, ...reqHeaders } = ctx.request.header;
ctx.request.header = reqHeaders; // eslint-disable-line no-param-reassign
}
await next();
});
app.use(convert(historyApiFallback(options.historyFallback)));
}
};
const statik = (root, opts = {}) => {
const paths = [].concat(root || options.static);
staticPaths = paths;
for (const path of paths) {
app.use(koaStatic(path, opts));
}
};
const proxy = (...args) => convert(createProxyMiddleware(...args));
const websocket = () => app.use(wsMiddleware);
proxy.skip = true;
// by default, middleware are executed in the order they appear here.
// the order of the properties returned in this object are important.
return {
compress: onetime(compress),
headers: onetime(headers),
historyFallback: onetime(historyFallback),
static: onetime(statik),
websocket: onetime(websocket),
proxy,
four0four: onetime(four0four)
};
};
module.exports = { getBuiltins };