2022-05-23 21:16:56 +00:00
|
|
|
import { NextApiRequest, NextApiResponse } from 'next'
|
|
|
|
import { promisify } from 'util'
|
|
|
|
import { pipeline } from 'stream'
|
2022-07-10 22:03:15 +00:00
|
|
|
import { getFunctionUrl } from 'common/api'
|
2022-05-23 21:16:56 +00:00
|
|
|
import fetch, { Headers, Response } from 'node-fetch'
|
|
|
|
|
|
|
|
function getProxiedRequestHeaders(req: NextApiRequest, whitelist: string[]) {
|
|
|
|
const result = new Headers()
|
2022-05-26 21:41:24 +00:00
|
|
|
for (const name of whitelist) {
|
2022-05-23 21:16:56 +00:00
|
|
|
const v = req.headers[name.toLowerCase()]
|
|
|
|
if (Array.isArray(v)) {
|
2022-05-26 21:41:24 +00:00
|
|
|
for (const vv of v) {
|
2022-05-23 21:16:56 +00:00
|
|
|
result.append(name, vv)
|
|
|
|
}
|
|
|
|
} else if (v != null) {
|
|
|
|
result.append(name, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result.append('X-Forwarded-For', req.socket.remoteAddress || '')
|
|
|
|
result.append('Via', 'Vercel public API')
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
function getProxiedResponseHeaders(res: Response, whitelist: string[]) {
|
|
|
|
const result: { [k: string]: string } = {}
|
2022-05-26 21:41:24 +00:00
|
|
|
for (const name of whitelist) {
|
2022-05-23 21:16:56 +00:00
|
|
|
const v = res.headers.get(name)
|
|
|
|
if (v != null) {
|
|
|
|
result[name] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2022-06-23 23:46:49 +00:00
|
|
|
export const fetchBackend = (req: NextApiRequest, name: string) => {
|
2022-06-06 19:46:06 +00:00
|
|
|
const url = getFunctionUrl(name)
|
2022-05-23 21:16:56 +00:00
|
|
|
const headers = getProxiedRequestHeaders(req, [
|
|
|
|
'Authorization',
|
|
|
|
'Content-Length',
|
|
|
|
'Content-Type',
|
|
|
|
'Origin',
|
|
|
|
])
|
2022-06-18 09:09:44 +00:00
|
|
|
const hasBody = req.method != 'HEAD' && req.method != 'GET'
|
2022-06-30 22:11:45 +00:00
|
|
|
const body = req.body ? JSON.stringify(req.body) : req
|
|
|
|
const opts = {
|
|
|
|
headers,
|
|
|
|
method: req.method,
|
|
|
|
body: hasBody ? body : undefined,
|
|
|
|
}
|
2022-06-18 09:09:44 +00:00
|
|
|
return fetch(url, opts)
|
2022-05-23 21:16:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const forwardResponse = async (
|
|
|
|
res: NextApiResponse,
|
|
|
|
backendRes: Response
|
|
|
|
) => {
|
|
|
|
const headers = getProxiedResponseHeaders(backendRes, [
|
|
|
|
'Access-Control-Allow-Origin',
|
|
|
|
'Content-Type',
|
|
|
|
'Cache-Control',
|
|
|
|
'ETag',
|
|
|
|
'Vary',
|
|
|
|
])
|
|
|
|
res.writeHead(backendRes.status, headers)
|
|
|
|
if (backendRes.body != null) {
|
|
|
|
return await promisify(pipeline)(backendRes.body, res)
|
|
|
|
}
|
|
|
|
}
|