-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvite.devProxy.ts
79 lines (73 loc) · 2.69 KB
/
vite.devProxy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { CookieJar } from 'tough-cookie'
import { IncomingMessage } from 'http'
import { Plugin } from 'vite'
import { Readable } from 'stream'
async function toBody(req: IncomingMessage): Promise<Buffer> {
const chunk: Buffer[] = []
return new Promise((res, rej) => {
req
.on('data', (c: Buffer) => chunk.push(c))
.on('end', () => res(Buffer.concat(chunk)))
.on('error', (e) => rej(e))
})
}
export default function devProxy(): Plugin {
const cookieJar = new CookieJar()
return {
name: 'vite-plugin-dev-proxy',
apply: 'serve',
configureServer(server) {
server.middlewares.use((req, res, next) => {
void (async () => {
if (req.url?.startsWith('/__vite_dev_proxy__')) {
const targetUrl = new URL(
new URL(req.url, 'http://localhost').searchParams.get('url')!,
)
console.log('Proxy:', req.method, targetUrl.toString())
try {
const proxyResponse = await fetch(targetUrl, {
method: req.method,
headers: {
...(req.headers as object),
cookie: cookieJar.getCookieStringSync(targetUrl.href),
},
redirect: 'manual',
body: ['POST', 'PUT'].includes(req.method ?? '')
? await toBody(req)
: undefined,
})
proxyResponse.headers
.getSetCookie()
.forEach((cookieStr) =>
cookieJar.setCookieSync(cookieStr, targetUrl.href),
)
proxyResponse.headers.forEach((v, k) => {
//TODO 在响应中添加正确的content-length
if (['content-encoding', 'content-length'].includes(k)) return
if (k.toLowerCase() === 'location') {
res.setHeader(
k,
new URL(req.url!, 'http://localhost').pathname +
'?url=' +
encodeURIComponent(v),
)
return
}
res.setHeader(k, v)
})
res.writeHead(proxyResponse.status)
if (proxyResponse.body)
Readable.fromWeb(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
proxyResponse.body as any,
).pipe(res, { end: true })
else res.end() // 没有响应正文
} catch (e) {
console.error('Proxy failed', req.method, targetUrl, e)
}
} else next() // 非__vite_dev_proxy__请求
})()
})
},
}
}