feat: implement CORS proxy for Matrix homeservers during development and refactor call handling logic

This commit is contained in:
2026-04-20 22:23:42 +10:00
parent 13a0c98d1d
commit 8060d50a6f
8 changed files with 221 additions and 48 deletions

View File

@@ -135,6 +135,83 @@ function servePublicAssets() {
};
}
// CORS proxy for Matrix homeservers during development
function corsProxyMiddleware() {
return {
name: 'vite-plugin-cors-proxy',
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
// Proxy /.well-known requests: /_matrix-cors-proxy/homeserver.com/.well-known/matrix/client
const corsProxyMatch = req.url?.match(/^\/_matrix-cors-proxy\/([^/]+)(\/.*)/);
if (corsProxyMatch) {
const [, hostname, pathname] = corsProxyMatch;
const targetUrl = `https://${hostname}${pathname}`;
console.log(`[CORS Proxy] ${req.method} ${req.url}`);
console.log(`[CORS Proxy] Target: ${targetUrl}`);
// Handle preflight OPTIONS request
if (req.method === 'OPTIONS') {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.writeHead(204);
res.end();
return;
}
try {
// Collect request body for POST/PUT
let body = null;
if (req.method === 'POST' || req.method === 'PUT') {
const chunks = [];
for await (const chunk of req) {
chunks.push(chunk);
}
body = Buffer.concat(chunks).toString();
console.log(`[CORS Proxy] Request body:`, body);
}
// Forward request with method, headers, and body
const fetchOptions = {
method: req.method,
headers: {
'Content-Type': req.headers['content-type'] || 'application/json',
'Authorization': req.headers['authorization'] || '',
},
};
if (body) {
fetchOptions.body = body;
}
const response = await fetch(targetUrl, fetchOptions);
const data = await response.text();
console.log(`[CORS Proxy] Response status: ${response.status}`);
console.log(`[CORS Proxy] Response data:`, data.substring(0, 500));
// Set CORS headers
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.setHeader('Content-Type', response.headers.get('content-type') || 'application/json');
res.writeHead(response.status);
res.end(data);
} catch (error) {
console.error(`[CORS Proxy] Error for ${targetUrl}:`, error);
res.writeHead(500);
res.end(JSON.stringify({ error: error.message }));
}
} else {
next();
}
});
},
};
}
export default defineConfig({
appType: 'spa',
publicDir: false,
@@ -143,12 +220,14 @@ export default defineConfig({
server: {
port: 38347,
host: '0.0.0.0',
cors: true, // Enable CORS for dev server
fs: {
// Allow serving files from one level up to the project root
allow: ['..'],
},
},
plugins: [
corsProxyMiddleware(), // Add CORS proxy for development
serverMatrixSdkCryptoWasm('/node_modules/.vite/deps/pkg/matrix_sdk_crypto_wasm_bg.wasm'),
serveGifWorker(),
servePublicAssets(),