Spaces:
Sleeping
Sleeping
| /** | |
| * 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 + | |
| ').' | |
| ) | |
| } | |
| } | |