From 566ad75c0ecba9a6d11e0dbc36337df788a31e90 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Tue, 21 Apr 2026 16:48:01 +0700 Subject: [PATCH] fix(qa): resolve remaining console errors & network errors on main routes (TEC-3079) - fix(web): add ws:// to CSP connect-src for Socket.IO WebSocket connections - fix(web): guard priceChangePct?.d7 / priceChangePct?.d30 against null in KpiStrip - fix(api): add web-vitals POST to CSRF exclusion in both app.module and shared.module - fix(api): use controller-relative path (web-vitals) not prefixed path for NestJS .exclude() Result: 0 console errors, 0 network 4xx/5xx on /, /login, /register, /search Co-Authored-By: Paperclip --- apps/api/src/app.module.ts | 2 ++ apps/api/src/modules/shared/shared.module.ts | 2 ++ apps/web/app/[locale]/(public)/page.tsx | 4 ++-- apps/web/next.config.js | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 97bcabc..cc98d4e 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -140,6 +140,8 @@ export class AppModule implements NestModule { .exclude( { path: 'health', method: RequestMethod.GET }, { path: 'health/(.*)', method: RequestMethod.GET }, + { path: 'api/v1/web-vitals', method: RequestMethod.POST }, // sendBeacon cannot send CSRF headers + { path: 'web-vitals', method: RequestMethod.POST }, // middleware exclude uses controller-relative path ) .forRoutes('*'); } diff --git a/apps/api/src/modules/shared/shared.module.ts b/apps/api/src/modules/shared/shared.module.ts index 59eb88a..3888891 100644 --- a/apps/api/src/modules/shared/shared.module.ts +++ b/apps/api/src/modules/shared/shared.module.ts @@ -72,6 +72,8 @@ export class SharedModule implements NestModule { { path: 'auth/refresh', method: RequestMethod.POST }, { path: 'auth/exchange-token', method: RequestMethod.POST }, { path: 'auth/logout', method: RequestMethod.POST }, + { path: 'api/v1/web-vitals', method: RequestMethod.POST }, // sendBeacon cannot send CSRF headers + { path: 'web-vitals', method: RequestMethod.POST }, // middleware exclude uses controller-relative path ) .forRoutes('*'); } diff --git a/apps/web/app/[locale]/(public)/page.tsx b/apps/web/app/[locale]/(public)/page.tsx index e35a8ec..d9a5b7d 100644 --- a/apps/web/app/[locale]/(public)/page.tsx +++ b/apps/web/app/[locale]/(public)/page.tsx @@ -139,7 +139,7 @@ function KpiStrip({ city }: { city: string }) { } loading={isLoading} @@ -147,7 +147,7 @@ function KpiStrip({ city }: { city: string }) { } loading={isLoading} diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 0c2190e..b240220 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -43,7 +43,7 @@ const nextConfig = { "style-src 'self' 'unsafe-inline' https://api.mapbox.com", "img-src 'self' data: blob: https://*.mapbox.com https://*.tiles.mapbox.com https:", "font-src 'self' data:", - `connect-src 'self' https://*.mapbox.com https://api.mapbox.com https://events.mapbox.com https://api.goodgo.vn${process.env.NODE_ENV !== 'production' ? ' http://localhost:3001 http://localhost:3011 http://localhost:9000' : ''}`, + `connect-src 'self' https://*.mapbox.com https://api.mapbox.com https://events.mapbox.com https://api.goodgo.vn${process.env.NODE_ENV !== 'production' ? ' http://localhost:3001 http://localhost:3011 http://localhost:9000 ws://localhost:3001 ws://localhost:3011' : ''}`, "worker-src 'self' blob:", "child-src 'self' blob:", "frame-ancestors 'none'",