You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							188 lines
						
					
					
						
							5.0 KiB
						
					
					
				
			
		
		
	
	
							188 lines
						
					
					
						
							5.0 KiB
						
					
					
				'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/641 | 
						|
function 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-return | 
						|
function 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, | 
						|
};
 | 
						|
 |