forked from webpack/webpack-dev-middleware
/
middleware.js
116 lines (96 loc) · 2.83 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
import path from 'path';
import mime from 'mime-types';
import getFilenameFromUrl from './utils/getFilenameFromUrl';
import handleRangeHeaders from './utils/handleRangeHeaders';
import ready from './utils/ready';
export default function wrapper(context) {
return async function middleware(req, res, next) {
const acceptedMethods = context.options.methods || ['GET', 'HEAD'];
// fixes #282. credit @cexoso. in certain edge situations res.locals is undefined.
// eslint-disable-next-line no-param-reassign
res.locals = res.locals || {};
if (!acceptedMethods.includes(req.method)) {
await goNext();
return;
}
ready(context, processRequest, req);
async function goNext() {
if (!context.options.serverSideRender) {
return next();
}
return new Promise((resolve) => {
ready(
context,
() => {
// eslint-disable-next-line no-param-reassign
res.locals.webpack = { devMiddleware: context };
resolve(next());
},
req
);
});
}
async function processRequest() {
const filename = getFilenameFromUrl(context, req.url);
const { headers } = context.options;
let content;
if (!filename) {
await goNext();
return;
}
try {
content = context.outputFileSystem.readFileSync(filename);
} catch (_ignoreError) {
await goNext();
return;
}
const contentTypeHeader = res.get
? res.get('Content-Type')
: res.getHeader('Content-Type');
if (!contentTypeHeader) {
// content-type name(like application/javascript; charset=utf-8) or false
const contentType = mime.contentType(path.extname(filename));
// Only set content-type header if media type is known
// https://tools.ietf.org/html/rfc7231#section-3.1.1.5
if (contentType) {
// Express API
if (res.set) {
res.set('Content-Type', contentType);
}
// Node.js API
else {
res.setHeader('Content-Type', contentType);
}
}
}
if (headers) {
const names = Object.keys(headers);
for (const name of names) {
// Express API
if (res.set) {
res.set(name, headers[name]);
}
// Node.js API
else {
res.setHeader(name, headers[name]);
}
}
}
// Buffer
content = handleRangeHeaders(context, content, req, res);
// Express API
if (res.send) {
res.send(content);
}
// Node.js API
else {
res.setHeader('Content-Length', content.length);
if (req.method === 'HEAD') {
res.end();
} else {
res.end(content);
}
}
}
};
}