206 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | ||
|  * Copyright (c) 2015-present, Facebook, Inc.
 | ||
|  *
 | ||
|  * This source code is licensed under the MIT license found in the
 | ||
|  * LICENSE file at
 | ||
|  * https://github.com/facebookincubator/create-react-app/blob/master/LICENSE
 | ||
|  */
 | ||
| 
 | ||
| const fs = require('fs')
 | ||
| const url = require('url')
 | ||
| const path = require('path')
 | ||
| const { chalk } = require('@vue/cli-shared-utils')
 | ||
| const address = require('address')
 | ||
| 
 | ||
| const defaultConfig = {
 | ||
|   logLevel: 'silent',
 | ||
|   secure: false,
 | ||
|   changeOrigin: true,
 | ||
|   ws: true,
 | ||
|   xfwd: true
 | ||
| }
 | ||
| 
 | ||
| module.exports = function prepareProxy (proxy, appPublicFolder) {
 | ||
|   // `proxy` lets you specify alternate servers for specific requests.
 | ||
|   // It can either be a string or an object conforming to the Webpack dev server proxy configuration
 | ||
|   // https://webpack.github.io/docs/webpack-dev-server.html
 | ||
|   if (!proxy) {
 | ||
|     return undefined
 | ||
|   }
 | ||
|   if (Array.isArray(proxy) || (typeof proxy !== 'object' && typeof proxy !== 'string')) {
 | ||
|     console.log(
 | ||
|       chalk.red(
 | ||
|         'When specified, "proxy" in package.json must be a string or an object.'
 | ||
|       )
 | ||
|     )
 | ||
|     console.log(
 | ||
|       chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".')
 | ||
|     )
 | ||
|     console.log(
 | ||
|       chalk.red(
 | ||
|         'Either remove "proxy" from package.json, or make it an object.'
 | ||
|       )
 | ||
|     )
 | ||
|     process.exit(1)
 | ||
|   }
 | ||
| 
 | ||
|   // If proxy is specified, let it handle any request except for
 | ||
|   // files in the public folder and requests to the WebpackDevServer socket endpoint.
 | ||
|   // https://github.com/facebook/create-react-app/issues/6720
 | ||
|   function mayProxy (pathname) {
 | ||
|     const maybePublicPath = path.resolve(appPublicFolder, pathname.slice(1))
 | ||
|     const isPublicFileRequest = fs.existsSync(maybePublicPath) && fs.statSync(maybePublicPath).isFile()
 | ||
|     const isWdsEndpointRequest = pathname.startsWith('/sockjs-node') // used by webpackHotDevClient
 | ||
|     return !(isPublicFileRequest || isWdsEndpointRequest)
 | ||
|   }
 | ||
| 
 | ||
|   function createProxyEntry (target, usersOnProxyReq, context) {
 | ||
|     // #2478
 | ||
|     // There're a little-known use case that the `target` field is an object rather than a string
 | ||
|     // https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/https.md
 | ||
|     if (typeof target === 'string' && process.platform === 'win32') {
 | ||
|       target = resolveLoopback(target)
 | ||
|     }
 | ||
|     return {
 | ||
|       target,
 | ||
|       context (pathname, req) {
 | ||
|         // is a static asset
 | ||
|         if (!mayProxy(pathname)) {
 | ||
|           return false
 | ||
|         }
 | ||
|         if (context) {
 | ||
|           // Explicit context, e.g. /api
 | ||
|           return pathname.match(context)
 | ||
|         } else {
 | ||
|           // not a static request
 | ||
|           if (req.method !== 'GET') {
 | ||
|             return true
 | ||
|           }
 | ||
|           // Heuristics: if request `accept`s text/html, we pick /index.html.
 | ||
|           // Modern browsers include text/html into `accept` header when navigating.
 | ||
|           // However API calls like `fetch()` won’t generally accept text/html.
 | ||
|           // If this heuristic doesn’t work well for you, use a custom `proxy` object.
 | ||
|           return (
 | ||
|             req.headers.accept &&
 | ||
|             req.headers.accept.indexOf('text/html') === -1
 | ||
|           )
 | ||
|         }
 | ||
|       },
 | ||
|       onProxyReq (proxyReq, req, res) {
 | ||
|         if (usersOnProxyReq) {
 | ||
|           usersOnProxyReq(proxyReq, req, res)
 | ||
|         }
 | ||
|         // Browsers may send Origin headers even with same-origin
 | ||
|         // requests. To prevent CORS issues, we have to change
 | ||
|         // the Origin to match the target URL.
 | ||
|         if (!proxyReq.agent && proxyReq.getHeader('origin')) {
 | ||
|           proxyReq.setHeader('origin', target)
 | ||
|         }
 | ||
|       },
 | ||
|       onError: onProxyError(target)
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   // Support proxy as a string for those who are using the simple proxy option
 | ||
|   if (typeof proxy === 'string') {
 | ||
|     if (!/^http(s)?:\/\//.test(proxy)) {
 | ||
|       console.log(
 | ||
|         chalk.red(
 | ||
|           'When "proxy" is specified in package.json it must start with either http:// or https://'
 | ||
|         )
 | ||
|       )
 | ||
|       process.exit(1)
 | ||
|     }
 | ||
| 
 | ||
|     return [
 | ||
|       Object.assign({}, defaultConfig, createProxyEntry(proxy))
 | ||
|     ]
 | ||
|   }
 | ||
| 
 | ||
|   // Otherwise, proxy is an object so create an array of proxies to pass to webpackDevServer
 | ||
|   return Object.keys(proxy).map(context => {
 | ||
|     const config = proxy[context]
 | ||
|     if (!config.hasOwnProperty('target')) {
 | ||
|       console.log(
 | ||
|         chalk.red(
 | ||
|           'When `proxy` in package.json is an object, each `context` object must have a ' +
 | ||
|             '`target` property specified as a url string'
 | ||
|         )
 | ||
|       )
 | ||
|       process.exit(1)
 | ||
|     }
 | ||
|     const entry = createProxyEntry(config.target, config.onProxyReq, context)
 | ||
|     return Object.assign({}, defaultConfig, config, entry)
 | ||
|   })
 | ||
| }
 | ||
| 
 | ||
| function resolveLoopback (proxy) {
 | ||
|   const o = url.parse(proxy)
 | ||
|   o.host = undefined
 | ||
|   if (o.hostname !== 'localhost') {
 | ||
|     return proxy
 | ||
|   }
 | ||
|   // Unfortunately, many languages (unlike node) do not yet support IPv6.
 | ||
|   // This means even though localhost resolves to ::1, the application
 | ||
|   // must fall back to IPv4 (on 127.0.0.1).
 | ||
|   // We can re-enable this in a few years.
 | ||
|   /* try {
 | ||
|     o.hostname = address.ipv6() ? '::1' : '127.0.0.1';
 | ||
|   } catch (_ignored) {
 | ||
|     o.hostname = '127.0.0.1';
 | ||
|   }*/
 | ||
| 
 | ||
|   try {
 | ||
|     // Check if we're on a network; if we are, chances are we can resolve
 | ||
|     // localhost. Otherwise, we can just be safe and assume localhost is
 | ||
|     // IPv4 for maximum compatibility.
 | ||
|     if (!address.ip()) {
 | ||
|       o.hostname = '127.0.0.1'
 | ||
|     }
 | ||
|   } catch (_ignored) {
 | ||
|     o.hostname = '127.0.0.1'
 | ||
|   }
 | ||
|   return url.format(o)
 | ||
| }
 | ||
| 
 | ||
| // We need to provide a custom onError function for httpProxyMiddleware.
 | ||
| // It allows us to log custom error messages on the console.
 | ||
| function onProxyError (proxy) {
 | ||
|   return (err, req, res) => {
 | ||
|     const host = req.headers && req.headers.host
 | ||
|     console.log(
 | ||
|       chalk.red('Proxy error:') +
 | ||
|         ' Could not proxy request ' +
 | ||
|         chalk.cyan(req.url) +
 | ||
|         ' from ' +
 | ||
|         chalk.cyan(host) +
 | ||
|         ' to ' +
 | ||
|         chalk.cyan(proxy) +
 | ||
|         '.'
 | ||
|     )
 | ||
|     console.log(
 | ||
|       'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
 | ||
|         chalk.cyan(err.code) +
 | ||
|         ').'
 | ||
|     )
 | ||
|     console.log()
 | ||
| 
 | ||
|     // And immediately send the proper error response to the client.
 | ||
|     // Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
 | ||
|     if (res.writeHead && !res.headersSent) {
 | ||
|       res.writeHead(500)
 | ||
|     }
 | ||
|     res.end(
 | ||
|       'Proxy error: Could not proxy request ' +
 | ||
|         req.url +
 | ||
|         ' from ' +
 | ||
|         host +
 | ||
|         ' to ' +
 | ||
|         proxy +
 | ||
|         ' (' +
 | ||
|         err.code +
 | ||
|         ').'
 | ||
|     )
 | ||
|   }
 | ||
| }
 | 
