1 |
|
2 |
|
3 |
|
4 |
|
5 | const path = require('path')
|
6 | const urlUtils = require('url')
|
7 | const koaHttpProxy = require('koa-better-http-proxy')
|
8 | const compose = require('koa-compose')
|
9 | const { IS_DEBUG } = require('./../utils/env')
|
10 | const logger = require('./../logger/koa-logger')('proxyMiddleWare')
|
11 | const appConfig = require(path.join(process.cwd(), 'app.config'))
|
12 | const needToken = !!appConfig.token
|
13 | let tokenManager
|
14 | if (needToken) {
|
15 | tokenManager = require('./token')(appConfig.token)
|
16 | }
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | module.exports = function () {
|
22 | async function preProxyMiddleware(ctx, next) {
|
23 | const url = ctx.url
|
24 | const staticRequest = url.startsWith('/api')
|
25 | logger.info(`Request '${url}'`)
|
26 | let proxyTarget
|
27 | let proxyConfig = appConfig.proxy
|
28 |
|
29 | for (const [prefix, target] of Object.entries(proxyConfig)) {
|
30 | if (url.startsWith(prefix)) {
|
31 |
|
32 | if (staticRequest) ctx.url = url.replace(prefix, '')
|
33 | proxyTarget = target
|
34 | ctx._proxyTarget = proxyTarget
|
35 | break
|
36 | }
|
37 | }
|
38 | if (!proxyTarget) {
|
39 | logger.info('Proxy not found, skipped')
|
40 | return Promise.resolve()
|
41 | }
|
42 | logger.info(`Will be Agent to '${proxyTarget + ctx.url}'`)
|
43 | return next()
|
44 | }
|
45 |
|
46 | |
47 |
|
48 |
|
49 | return compose([
|
50 | preProxyMiddleware,
|
51 | koaHttpProxy(
|
52 | (ctx) => {
|
53 | return ctx._proxyTarget
|
54 | },
|
55 | {
|
56 |
|
57 | parseReqBody: false,
|
58 | |
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | async proxyReqOptDecorator(proxyReqOpts, ctx) {
|
65 | const parsedTarget = urlUtils.parse(ctx._proxyTarget, true)
|
66 | proxyReqOpts.host = parsedTarget.hostname
|
67 | proxyReqOpts.port = parsedTarget.port
|
68 | proxyReqOpts.https = parsedTarget.protocol === 'https:'
|
69 |
|
70 |
|
71 | if (IS_DEBUG) {
|
72 | delete proxyReqOpts.headers.Referer
|
73 | delete proxyReqOpts.headers.Origin
|
74 | }
|
75 |
|
76 | ctx._proxyStartTime = Date.now()
|
77 | if (!needToken) {
|
78 | return proxyReqOpts
|
79 | }
|
80 | return await tokenManager.handleRequest(ctx)
|
81 | .then((additionalHeaders) => {
|
82 | Object.assign(proxyReqOpts.headers, additionalHeaders)
|
83 | })
|
84 | .then(() => {
|
85 | return proxyReqOpts
|
86 | })
|
87 | },
|
88 | |
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | async userResDecorator(proxyRes, proxyResData, ctx) {
|
96 | logger.info('Interface ProxyRes headers:', '\n', JSON.stringify(ctx.response.headers, null, 2))
|
97 | const location = `${ctx._proxyTarget}${ctx.url}`
|
98 | logger.info(`Interface Proxy request '${location}' completed(${proxyRes.statusCode}), costing ${Date.now() - ctx._proxyStartTime}ms.`)
|
99 | if (!needToken) {
|
100 | return proxyResData
|
101 | }
|
102 | return await tokenManager.handleResponse(ctx)
|
103 | .then(() => {
|
104 | return proxyResData
|
105 | })
|
106 | },
|
107 | }),
|
108 | ])
|
109 | }
|