Projekt

Obecné

Profil

Stáhnout (4.97 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2

    
3
const path = require('path');
4
const { parse } = require('url');
5
const querystring = require('querystring');
6

    
7
const parseRange = require('range-parser');
8

    
9
const HASH_REGEXP = /[0-9a-f]{10,}/;
10

    
11
// support for multi-compiler configuration
12
// see: https://github.com/webpack/webpack-dev-server/issues/641
13
function getPaths(publicPath, compiler, url) {
14
  const compilers = compiler && compiler.compilers;
15
  if (Array.isArray(compilers)) {
16
    let compilerPublicPath;
17

    
18
    // the path portion of compilerPublicPath
19
    let compilerPublicPathBase;
20

    
21
    for (let i = 0; i < compilers.length; i++) {
22
      compilerPublicPath =
23
        compilers[i].options &&
24
        compilers[i].options.output &&
25
        compilers[i].options.output.publicPath;
26

    
27
      if (compilerPublicPath) {
28
        compilerPublicPathBase =
29
          compilerPublicPath.indexOf('/') === 0
30
            ? compilerPublicPath // eslint-disable-next-line
31
            : // handle the case where compilerPublicPath is a URL with hostname
32
              parse(compilerPublicPath).pathname;
33

    
34
        // check the url vs the path part of the compilerPublicPath
35
        if (url.indexOf(compilerPublicPathBase) === 0) {
36
          return {
37
            publicPath: compilerPublicPath,
38
            outputPath: compilers[i].outputPath,
39
          };
40
        }
41
      }
42
    }
43
  }
44
  return {
45
    publicPath,
46
    outputPath: compiler.outputPath,
47
  };
48
}
49

    
50
// eslint-disable-next-line consistent-return
51
function ready(context, fn, req) {
52
  if (context.state) {
53
    return fn(context.webpackStats);
54
  }
55

    
56
  context.log.info(`wait until bundle finished: ${req.url || fn.name}`);
57
  context.callbacks.push(fn);
58
}
59

    
60
module.exports = {
61
  getFilenameFromUrl(pubPath, compiler, url) {
62
    const { outputPath, publicPath } = getPaths(pubPath, compiler, url);
63
    // localPrefix is the folder our bundle should be in
64
    const localPrefix = parse(publicPath || '/', false, true);
65
    const urlObject = parse(url);
66
    let filename;
67

    
68
    const hostNameIsTheSame = localPrefix.hostname === urlObject.hostname;
69

    
70
    // publicPath has the hostname that is not the same as request url's, should fail
71
    if (
72
      localPrefix.hostname !== null &&
73
      urlObject.hostname !== null &&
74
      !hostNameIsTheSame
75
    ) {
76
      return false;
77
    }
78

    
79
    // publicPath is not in url, so it should fail
80
    if (publicPath && hostNameIsTheSame && url.indexOf(publicPath) !== 0) {
81
      return false;
82
    }
83

    
84
    // strip localPrefix from the start of url
85
    if (urlObject.pathname.indexOf(localPrefix.pathname) === 0) {
86
      filename = urlObject.pathname.substr(localPrefix.pathname.length);
87
    }
88

    
89
    if (
90
      !urlObject.hostname &&
91
      localPrefix.hostname &&
92
      url.indexOf(localPrefix.path) !== 0
93
    ) {
94
      return false;
95
    }
96

    
97
    let uri = outputPath;
98

    
99
    /* istanbul ignore if */
100
    if (process.platform === 'win32') {
101
      // Path Handling for Microsoft Windows
102
      if (filename) {
103
        uri = path.posix.join(outputPath || '', querystring.unescape(filename));
104

    
105
        if (!path.win32.isAbsolute(uri)) {
106
          uri = `/${uri}`;
107
        }
108
      }
109

    
110
      return uri;
111
    }
112

    
113
    // Path Handling for all other operating systems
114
    if (filename) {
115
      uri = path.posix.join(outputPath || '', filename);
116

    
117
      if (!path.posix.isAbsolute(uri)) {
118
        uri = `/${uri}`;
119
      }
120
    }
121

    
122
    // if no matches, use outputPath as filename
123
    return querystring.unescape(uri);
124
  },
125

    
126
  handleRangeHeaders(content, req, res) {
127
    // assumes express API. For other servers, need to add logic to access
128
    // alternative header APIs
129
    res.setHeader('Accept-Ranges', 'bytes');
130

    
131
    if (req.headers.range) {
132
      const ranges = parseRange(content.length, req.headers.range);
133

    
134
      // unsatisfiable
135
      if (ranges === -1) {
136
        res.setHeader('Content-Range', `bytes */${content.length}`);
137
        // eslint-disable-next-line no-param-reassign
138
        res.statusCode = 416;
139
      }
140

    
141
      // valid (syntactically invalid/multiple ranges are treated as a
142
      // regular response)
143
      if (ranges !== -2 && ranges.length === 1) {
144
        const { length } = content;
145

    
146
        // Content-Range
147
        // eslint-disable-next-line no-param-reassign
148
        res.statusCode = 206;
149
        res.setHeader(
150
          'Content-Range',
151
          `bytes ${ranges[0].start}-${ranges[0].end}/${length}`
152
        );
153

    
154
        // eslint-disable-next-line no-param-reassign
155
        content = content.slice(ranges[0].start, ranges[0].end + 1);
156
      }
157
    }
158

    
159
    return content;
160
  },
161

    
162
  handleRequest(context, filename, processRequest, req) {
163
    // in lazy mode, rebuild on bundle request
164
    if (
165
      context.options.lazy &&
166
      (!context.options.filename || context.options.filename.test(filename))
167
    ) {
168
      context.rebuild();
169
    }
170

    
171
    if (HASH_REGEXP.test(filename)) {
172
      try {
173
        if (context.fs.statSync(filename).isFile()) {
174
          processRequest();
175
          return;
176
        }
177
      } catch (e) {
178
        // eslint-disable-line
179
      }
180
    }
181

    
182
    ready(context, processRequest, req);
183
  },
184

    
185
  noop: () => {},
186

    
187
  ready,
188
};
(6-6/6)