fix(dev): enable Vite session auth proxy
This commit is contained in:
@@ -9,6 +9,11 @@ const ROOT = path.resolve(DIR, '../..');
|
|||||||
|
|
||||||
type BasicAuth = { username: string; password: string };
|
type BasicAuth = { username: string; password: string };
|
||||||
|
|
||||||
|
function stripTrailingSlashes(p: string): string {
|
||||||
|
const out = p.replace(/\/+$/, '');
|
||||||
|
return out || '/';
|
||||||
|
}
|
||||||
|
|
||||||
function readApiReadToken(): string | undefined {
|
function readApiReadToken(): string | undefined {
|
||||||
if (process.env.API_READ_TOKEN) return process.env.API_READ_TOKEN;
|
if (process.env.API_READ_TOKEN) return process.env.API_READ_TOKEN;
|
||||||
const p = path.join(ROOT, 'tokens', 'read.json');
|
const p = path.join(ROOT, 'tokens', 'read.json');
|
||||||
@@ -56,30 +61,98 @@ function readProxyBasicAuth(): BasicAuth | undefined {
|
|||||||
|
|
||||||
const apiReadToken = readApiReadToken();
|
const apiReadToken = readApiReadToken();
|
||||||
const proxyBasicAuth = readProxyBasicAuth();
|
const proxyBasicAuth = readProxyBasicAuth();
|
||||||
|
const apiProxyTarget = process.env.API_PROXY_TARGET || 'http://localhost:8787';
|
||||||
|
|
||||||
|
function parseUrl(v: string): URL | undefined {
|
||||||
|
try {
|
||||||
|
return new URL(v);
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiProxyTargetUrl = parseUrl(apiProxyTarget);
|
||||||
|
const apiProxyTargetPath = stripTrailingSlashes(apiProxyTargetUrl?.pathname || '/');
|
||||||
|
const apiProxyTargetEndsWithApi = apiProxyTargetPath.endsWith('/api');
|
||||||
|
|
||||||
|
function inferUiProxyTarget(apiTarget: string): string | undefined {
|
||||||
|
try {
|
||||||
|
const u = new URL(apiTarget);
|
||||||
|
const p = stripTrailingSlashes(u.pathname || '/');
|
||||||
|
if (!p.endsWith('/api')) return undefined;
|
||||||
|
const basePath = p.slice(0, -'/api'.length) || '/';
|
||||||
|
u.pathname = basePath;
|
||||||
|
u.search = '';
|
||||||
|
u.hash = '';
|
||||||
|
const out = u.toString();
|
||||||
|
return out.endsWith('/') ? out.slice(0, -1) : out;
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uiProxyTarget =
|
||||||
|
process.env.FRONTEND_PROXY_TARGET ||
|
||||||
|
process.env.UI_PROXY_TARGET ||
|
||||||
|
process.env.AUTH_PROXY_TARGET ||
|
||||||
|
inferUiProxyTarget(apiProxyTarget) ||
|
||||||
|
(apiProxyTargetUrl && apiProxyTargetPath === '/' ? stripTrailingSlashes(apiProxyTargetUrl.toString()) : undefined);
|
||||||
|
|
||||||
|
function applyProxyBasicAuth(proxyReq: any) {
|
||||||
|
if (!proxyBasicAuth) return false;
|
||||||
|
const b64 = Buffer.from(`${proxyBasicAuth.username}:${proxyBasicAuth.password}`, 'utf8').toString('base64');
|
||||||
|
proxyReq.setHeader('Authorization', `Basic ${b64}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rewriteSetCookieForLocalDevHttp(proxyRes: any) {
|
||||||
|
const v = proxyRes?.headers?.['set-cookie'];
|
||||||
|
if (!v) return;
|
||||||
|
const rewrite = (cookie: string) => {
|
||||||
|
let out = cookie.replace(/;\s*secure\b/gi, '');
|
||||||
|
out = out.replace(/;\s*domain=[^;]+/gi, '');
|
||||||
|
out = out.replace(/;\s*samesite=none\b/gi, '; SameSite=Lax');
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
proxyRes.headers['set-cookie'] = Array.isArray(v) ? v.map(rewrite) : rewrite(String(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxy: Record<string, any> = {
|
||||||
|
'/api': {
|
||||||
|
target: apiProxyTarget,
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (p: string) => (apiProxyTargetEndsWithApi ? p.replace(/^\/api/, '') : p),
|
||||||
|
configure: (p: any) => {
|
||||||
|
p.on('proxyReq', (proxyReq: any) => {
|
||||||
|
if (applyProxyBasicAuth(proxyReq)) return;
|
||||||
|
if (apiReadToken) proxyReq.setHeader('Authorization', `Bearer ${apiReadToken}`);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (uiProxyTarget) {
|
||||||
|
for (const prefix of ['/whoami', '/auth', '/logout']) {
|
||||||
|
proxy[prefix] = {
|
||||||
|
target: uiProxyTarget,
|
||||||
|
changeOrigin: true,
|
||||||
|
configure: (p: any) => {
|
||||||
|
p.on('proxyReq', (proxyReq: any) => {
|
||||||
|
applyProxyBasicAuth(proxyReq);
|
||||||
|
});
|
||||||
|
p.on('proxyRes', (proxyRes: any) => {
|
||||||
|
rewriteSetCookieForLocalDevHttp(proxyRes);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
strictPort: true,
|
strictPort: true,
|
||||||
proxy: {
|
proxy,
|
||||||
'/api': {
|
|
||||||
target: process.env.API_PROXY_TARGET || 'http://localhost:8787',
|
|
||||||
changeOrigin: true,
|
|
||||||
rewrite: (p) => p.replace(/^\/api/, ''),
|
|
||||||
configure: (proxy) => {
|
|
||||||
proxy.on('proxyReq', (proxyReq) => {
|
|
||||||
if (proxyBasicAuth) {
|
|
||||||
const b64 = Buffer.from(`${proxyBasicAuth.username}:${proxyBasicAuth.password}`, 'utf8').toString(
|
|
||||||
'base64'
|
|
||||||
);
|
|
||||||
proxyReq.setHeader('Authorization', `Basic ${b64}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (apiReadToken) proxyReq.setHeader('Authorization', `Bearer ${apiReadToken}`);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user