| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 | 'use strict';const path = require('path');const { parse } = require('url');const querystring = require('querystring');const parseRange = require('range-parser');const HASH_REGEXP = /[0-9a-f]{10,}/;// support for multi-compiler configuration// see: https://github.com/webpack/webpack-dev-server/issues/641function getPaths(publicPath, compiler, url) {  const compilers = compiler && compiler.compilers;  if (Array.isArray(compilers)) {    let compilerPublicPath;    // the path portion of compilerPublicPath    let compilerPublicPathBase;    for (let i = 0; i < compilers.length; i++) {      compilerPublicPath =        compilers[i].options &&        compilers[i].options.output &&        compilers[i].options.output.publicPath;      if (compilerPublicPath) {        compilerPublicPathBase =          compilerPublicPath.indexOf('/') === 0            ? compilerPublicPath // eslint-disable-next-line            : // handle the case where compilerPublicPath is a URL with hostname              parse(compilerPublicPath).pathname;        // check the url vs the path part of the compilerPublicPath        if (url.indexOf(compilerPublicPathBase) === 0) {          return {            publicPath: compilerPublicPath,            outputPath: compilers[i].outputPath,          };        }      }    }  }  return {    publicPath,    outputPath: compiler.outputPath,  };}// eslint-disable-next-line consistent-returnfunction ready(context, fn, req) {  if (context.state) {    return fn(context.webpackStats);  }  context.log.info(`wait until bundle finished: ${req.url || fn.name}`);  context.callbacks.push(fn);}module.exports = {  getFilenameFromUrl(pubPath, compiler, url) {    const { outputPath, publicPath } = getPaths(pubPath, compiler, url);    // localPrefix is the folder our bundle should be in    const localPrefix = parse(publicPath || '/', false, true);    const urlObject = parse(url);    let filename;    const hostNameIsTheSame = localPrefix.hostname === urlObject.hostname;    // publicPath has the hostname that is not the same as request url's, should fail    if (      localPrefix.hostname !== null &&      urlObject.hostname !== null &&      !hostNameIsTheSame    ) {      return false;    }    // publicPath is not in url, so it should fail    if (publicPath && hostNameIsTheSame && url.indexOf(publicPath) !== 0) {      return false;    }    // strip localPrefix from the start of url    if (urlObject.pathname.indexOf(localPrefix.pathname) === 0) {      filename = urlObject.pathname.substr(localPrefix.pathname.length);    }    if (      !urlObject.hostname &&      localPrefix.hostname &&      url.indexOf(localPrefix.path) !== 0    ) {      return false;    }    let uri = outputPath;    /* istanbul ignore if */    if (process.platform === 'win32') {      // Path Handling for Microsoft Windows      if (filename) {        uri = path.posix.join(outputPath || '', querystring.unescape(filename));        if (!path.win32.isAbsolute(uri)) {          uri = `/${uri}`;        }      }      return uri;    }    // Path Handling for all other operating systems    if (filename) {      uri = path.posix.join(outputPath || '', filename);      if (!path.posix.isAbsolute(uri)) {        uri = `/${uri}`;      }    }    // if no matches, use outputPath as filename    return querystring.unescape(uri);  },  handleRangeHeaders(content, req, res) {    // assumes express API. For other servers, need to add logic to access    // alternative header APIs    res.setHeader('Accept-Ranges', 'bytes');    if (req.headers.range) {      const ranges = parseRange(content.length, req.headers.range);      // unsatisfiable      if (ranges === -1) {        res.setHeader('Content-Range', `bytes */${content.length}`);        // eslint-disable-next-line no-param-reassign        res.statusCode = 416;      }      // valid (syntactically invalid/multiple ranges are treated as a      // regular response)      if (ranges !== -2 && ranges.length === 1) {        const { length } = content;        // Content-Range        // eslint-disable-next-line no-param-reassign        res.statusCode = 206;        res.setHeader(          'Content-Range',          `bytes ${ranges[0].start}-${ranges[0].end}/${length}`        );        // eslint-disable-next-line no-param-reassign        content = content.slice(ranges[0].start, ranges[0].end + 1);      }    }    return content;  },  handleRequest(context, filename, processRequest, req) {    // in lazy mode, rebuild on bundle request    if (      context.options.lazy &&      (!context.options.filename || context.options.filename.test(filename))    ) {      context.rebuild();    }    if (HASH_REGEXP.test(filename)) {      try {        if (context.fs.statSync(filename).isFile()) {          processRequest();          return;        }      } catch (e) {        // eslint-disable-line      }    }    ready(context, processRequest, req);  },  noop: () => {},  ready,};
 |