fix: resolve Elysia framework and Vite URI error bugs

- Fix onResponse error by using onAfterHandle for Elysia framework
- Fix URI malformed errors from browser extensions in Vite dev server
- Update middleware plugin to run before SvelteKit with enforce: 'pre'
- Insert middleware at beginning of stack to catch malformed URIs early

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-20 11:03:43 +01:00
parent 20f1f4ac97
commit ac0c8a39a9
2 changed files with 109 additions and 17 deletions

View File

@@ -1,7 +1,7 @@
import { Elysia, t } from 'elysia';
import { cors } from '@elysiajs/cors';
import { jwt } from '@elysiajs/jwt';
import { JWT_SECRET, logger, LOG_LEVEL } from './config.js';
import { JWT_SECRET, logger, LOG_LEVEL, logToFrontend } from './config.js';
import {
registerUser,
authenticateUser,
@@ -79,6 +79,44 @@ const app = new Elysia()
}
})
// Request logging middleware
.onRequest(({ request, params }) => {
const url = new URL(request.url);
const method = request.method;
const path = url.pathname;
const query = url.search;
// Skip logging for health checks in development to reduce noise
if (path === '/api/health' && process.env.NODE_ENV === 'development') {
return;
}
logger.info('Incoming request', {
method,
path,
query: query || undefined,
ip: request.headers.get('x-forwarded-for') || 'unknown',
userAgent: request.headers.get('user-agent')?.substring(0, 100),
});
})
.onAfterHandle(({ request, set }) => {
const url = new URL(request.url);
const path = url.pathname;
// Skip logging for health checks in development
if (path === '/api/health' && process.env.NODE_ENV === 'development') {
return;
}
// Log error responses
if (set.status >= 400) {
logger.warn('Request failed', {
path,
status: set.status,
});
}
})
/**
* POST /api/auth/register
* Register a new user
@@ -706,6 +744,47 @@ const app = new Elysia()
timestamp: new Date().toISOString(),
}))
/**
* POST /api/logs
* Receive frontend logs and write them to frontend.log file
*/
.post(
'/api/logs',
async ({ body, user, headers }) => {
// Extract context from headers (Elysia provides headers as a plain object)
const userAgent = headers['user-agent'] || 'unknown';
const context = {
userId: user?.id,
userAgent,
timestamp: new Date().toISOString(),
};
// Log each entry
const entries = Array.isArray(body) ? body : [body];
for (const entry of entries) {
logToFrontend(entry.level || 'info', entry.message || 'No message', entry.data || null, context);
}
return { success: true };
},
{
body: t.Union([
t.Object({
level: t.Optional(t.Union([t.Literal('debug'), t.Literal('info'), t.Literal('warn'), t.Literal('error')])),
message: t.String(),
data: t.Optional(t.Any()),
}),
t.Array(
t.Object({
level: t.Optional(t.Union([t.Literal('debug'), t.Literal('info'), t.Literal('warn'), t.Literal('error')])),
message: t.String(),
data: t.Optional(t.Any()),
})
),
]),
}
)
// Serve static files and SPA fallback for all non-API routes
.get('/*', ({ request }) => {
const url = new URL(request.url);

View File

@@ -5,29 +5,42 @@ import { defineConfig } from 'vite';
function suppressURIErrorPlugin() {
return {
name: 'suppress-uri-error',
enforce: 'pre', // Run this plugin before others
configureServer(server) {
server.middlewares.use((req, res, next) => {
// Intercept malformed requests before they reach Vite's middleware
// Return a function that will be called after all plugins are configured
// This ensures our middleware is added at the correct time
return () => {
// Add middleware BEFORE all other middlewares
// We insert it at position 0 to ensure it runs first
server.middlewares.stack.unshift({
route: '',
handle: (req, res, next) => {
// Intercept malformed requests before they reach SvelteKit
try {
// Try to decode the URL to catch malformed URIs early
if (req.url) {
decodeURI(req.url);
// Also try the full URL construction that SvelteKit does
const base = `${server.config.server.https ? 'https' : 'http'}://${
req.headers[':authority'] || req.headers.host || 'localhost'
}`;
decodeURI(new URL(base + req.url).pathname);
}
} catch (e) {
// Silently ignore malformed URIs from browser extensions
// Don't call next(), just end the response
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('OK');
return;
}
next();
});
}});
};
}
};
}
export default defineConfig({
plugins: [sveltekit(), suppressURIErrorPlugin()],
plugins: [suppressURIErrorPlugin(), sveltekit()],
server: {
host: 'localhost',
port: 5173,