diff --git a/api/_proxy.js b/api/_proxy.js index 1baf203..e0e0e67 100644 --- a/api/_proxy.js +++ b/api/_proxy.js @@ -68,21 +68,43 @@ function stripProxyPrefix(pathname, prefixes) { return pathname.slice(matchedPrefix.length) || '/'; } +function buildTargetPathFromQuery(incomingUrl, pathQueryParam) { + if (!pathQueryParam) { + return null; + } + + const pathFromQuery = incomingUrl.searchParams.get(pathQueryParam); + + if (!pathFromQuery) { + return '/'; + } + + incomingUrl.searchParams.delete(pathQueryParam); + + return pathFromQuery.startsWith('/') ? pathFromQuery : `/${pathFromQuery}`; +} + function buildTargetUrl(requestUrl, options, targetBase) { const incomingUrl = new URL(requestUrl, 'https://vercel.local'); - const pathname = stripProxyPrefix(incomingUrl.pathname, normalizeProxyPrefixes(options)); + const pathname = + buildTargetPathFromQuery(incomingUrl, options.pathQueryParam) ?? + stripProxyPrefix(incomingUrl.pathname, normalizeProxyPrefixes(options)); const targetUrl = new URL(pathname || '/', targetBase); - targetUrl.search = incomingUrl.search; + targetUrl.search = incomingUrl.searchParams.toString(); return targetUrl; } -async function proxyRequest(request, response, { envName, prefix, prefixes }) { +async function proxyRequest(request, response, { envName, pathQueryParam, prefix, prefixes }) { let targetUrl; try { - targetUrl = buildTargetUrl(request.url, { prefix, prefixes }, requireProxyTarget(envName)); + targetUrl = buildTargetUrl( + request.url, + { pathQueryParam, prefix, prefixes }, + requireProxyTarget(envName), + ); } catch (error) { response.statusCode = 500; response.setHeader('content-type', 'application/json; charset=utf-8'); diff --git a/api/_proxy.test.js b/api/_proxy.test.js index b1e8cd8..87130a6 100644 --- a/api/_proxy.test.js +++ b/api/_proxy.test.js @@ -43,4 +43,18 @@ describe('buildTargetUrl', () => { expect(targetUrl.toString()).toBe('https://backend.example.com/be10/api/v1/scan'); }); + + it('builds the target path from a Vercel rewrite query parameter', () => { + const targetUrl = buildTargetUrl( + '/api/be3?path=api/v1/scan/subscribe&guest_uuid=guest-1', + { + pathQueryParam: 'path', + }, + targetBase, + ); + + expect(targetUrl.toString()).toBe( + 'https://backend.example.com/api/v1/scan/subscribe?guest_uuid=guest-1', + ); + }); }); diff --git a/api/be1.js b/api/be1.js new file mode 100644 index 0000000..13e0ea6 --- /dev/null +++ b/api/be1.js @@ -0,0 +1,8 @@ +const { proxyRequest } = require('./_proxy'); + +module.exports = function handler(request, response) { + return proxyRequest(request, response, { + envName: 'BE1_PROXY_TARGET_URL', + pathQueryParam: 'path', + }); +}; diff --git a/api/be3.js b/api/be3.js new file mode 100644 index 0000000..b014c05 --- /dev/null +++ b/api/be3.js @@ -0,0 +1,8 @@ +const { proxyRequest } = require('./_proxy'); + +module.exports = function handler(request, response) { + return proxyRequest(request, response, { + envName: 'BE3_PROXY_TARGET_URL', + pathQueryParam: 'path', + }); +}; diff --git a/vercel.json b/vercel.json index 5d27ba5..3a54433 100644 --- a/vercel.json +++ b/vercel.json @@ -2,11 +2,11 @@ "rewrites": [ { "source": "/be1/:path*", - "destination": "/api/be1/:path*" + "destination": "/api/be1?path=:path*" }, { "source": "/be3/:path*", - "destination": "/api/be3/:path*" + "destination": "/api/be3?path=:path*" } ] }