From 6466cef2696c485130c529aad9baa9aa5e78b358 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 10 Feb 2025 21:14:58 -0800 Subject: [PATCH] Return server error. --- src/app/api/auth/login/route.ts | 2 +- src/app/api/send/route.ts | 286 ++++++++++++++++---------------- 2 files changed, 146 insertions(+), 142 deletions(-) diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts index 766c788c..7ae22e2b 100644 --- a/src/app/api/auth/login/route.ts +++ b/src/app/api/auth/login/route.ts @@ -31,7 +31,7 @@ export async function POST(request: Request) { const { id, role, createdAt } = user; - let token = null; + let token: string; if (redis.enabled) { token = await saveAuth({ userId: id, role }); diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index 8d841270..fce649da 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -29,170 +29,174 @@ const schema = z.object({ }); export async function POST(request: Request) { - // Bot check - if (!process.env.DISABLE_BOT_CHECK && isbot(request.headers.get('user-agent'))) { - return json({ beep: 'boop' }); - } - - const { body, error } = await parseRequest(request, schema, { skipAuth: true }); - - if (error) { - return error(); - } - - const { type, payload } = body; - - const { - website: websiteId, - hostname, - screen, - language, - url, - referrer, - name, - data, - title, - tag, - } = payload; - - // Cache check - let cache: { websiteId: string; sessionId: string; visitId: string; iat: number } | null = null; - const cacheHeader = request.headers.get('x-umami-cache'); - - if (cacheHeader) { - const result = await parseToken(cacheHeader, secret()); - - if (result) { - cache = result; + try { + // Bot check + if (!process.env.DISABLE_BOT_CHECK && isbot(request.headers.get('user-agent'))) { + return json({ beep: 'boop' }); } - } - // Find website - if (!cache?.websiteId) { - const website = await fetchWebsite(websiteId); + const { body, error } = await parseRequest(request, schema, { skipAuth: true }); - if (!website) { - return badRequest('Website not found.'); + if (error) { + return error(); } - } - // Client info - const { ip, userAgent, device, browser, os, country, subdivision1, subdivision2, city } = - await getClientInfo(request, payload); + const { type, payload } = body; - // IP block - if (hasBlockedIp(ip)) { - return forbidden(); - } + const { + website: websiteId, + hostname, + screen, + language, + url, + referrer, + name, + data, + title, + tag, + } = payload; - const sessionId = uuid(websiteId, hostname, ip, userAgent); + // Cache check + let cache: { websiteId: string; sessionId: string; visitId: string; iat: number } | null = null; + const cacheHeader = request.headers.get('x-umami-cache'); - // Find session - if (!clickhouse.enabled && !cache?.sessionId) { - const session = await fetchSession(websiteId, sessionId); + if (cacheHeader) { + const result = await parseToken(cacheHeader, secret()); - // Create a session if not found - if (!session) { - try { - await createSession({ - id: sessionId, - websiteId, - hostname, - browser, - os, - device, - screen, - language, - country, - subdivision1, - subdivision2, - city, - }); - } catch (e: any) { - if (!e.message.toLowerCase().includes('unique constraint')) { - return serverError(e); + if (result) { + cache = result; + } + } + + // Find website + if (!cache?.websiteId) { + const website = await fetchWebsite(websiteId); + + if (!website) { + return badRequest('Website not found.'); + } + } + + // Client info + const { ip, userAgent, device, browser, os, country, subdivision1, subdivision2, city } = + await getClientInfo(request, payload); + + // IP block + if (hasBlockedIp(ip)) { + return forbidden(); + } + + const sessionId = uuid(websiteId, hostname, ip, userAgent); + + // Find session + if (!clickhouse.enabled && !cache?.sessionId) { + const session = await fetchSession(websiteId, sessionId); + + // Create a session if not found + if (!session) { + try { + await createSession({ + id: sessionId, + websiteId, + hostname, + browser, + os, + device, + screen, + language, + country, + subdivision1, + subdivision2, + city, + }); + } catch (e: any) { + if (!e.message.toLowerCase().includes('unique constraint')) { + return serverError(e); + } } } } - } - // Visit info - const now = Math.floor(new Date().getTime() / 1000); - let visitId = cache?.visitId || uuid(sessionId, visitSalt()); - let iat = cache?.iat || now; + // Visit info + const now = Math.floor(new Date().getTime() / 1000); + let visitId = cache?.visitId || uuid(sessionId, visitSalt()); + let iat = cache?.iat || now; - // Expire visit after 30 minutes - if (now - iat > 1800) { - visitId = uuid(sessionId, visitSalt()); - iat = now; - } - - if (type === COLLECTION_TYPE.event) { - const base = hostname ? `http://${hostname}` : 'http://localhost'; - const currentUrl = new URL(url, base); - - let urlPath = currentUrl.pathname; - const urlQuery = currentUrl.search.substring(1); - const urlDomain = currentUrl.hostname.replace(/^www./, ''); - - if (process.env.REMOVE_TRAILING_SLASH) { - urlPath = urlPath.replace(/(.+)\/$/, '$1'); + // Expire visit after 30 minutes + if (now - iat > 1800) { + visitId = uuid(sessionId, visitSalt()); + iat = now; } - let referrerPath: string; - let referrerQuery: string; - let referrerDomain: string; + if (type === COLLECTION_TYPE.event) { + const base = hostname ? `http://${hostname}` : 'http://localhost'; + const currentUrl = new URL(url, base); - if (referrer) { - const referrerUrl = new URL(referrer, base); + let urlPath = currentUrl.pathname; + const urlQuery = currentUrl.search.substring(1); + const urlDomain = currentUrl.hostname.replace(/^www./, ''); - referrerPath = referrerUrl.pathname; - referrerQuery = referrerUrl.search.substring(1); - - if (referrerUrl.hostname !== 'localhost') { - referrerDomain = referrerUrl.hostname.replace(/^www\./, ''); + if (process.env.REMOVE_TRAILING_SLASH) { + urlPath = urlPath.replace(/(.+)\/$/, '$1'); } + + let referrerPath: string; + let referrerQuery: string; + let referrerDomain: string; + + if (referrer) { + const referrerUrl = new URL(referrer, base); + + referrerPath = referrerUrl.pathname; + referrerQuery = referrerUrl.search.substring(1); + + if (referrerUrl.hostname !== 'localhost') { + referrerDomain = referrerUrl.hostname.replace(/^www\./, ''); + } + } + + await saveEvent({ + websiteId, + sessionId, + visitId, + urlPath, + urlQuery, + referrerPath, + referrerQuery, + referrerDomain, + pageTitle: title, + eventName: name, + eventData: data, + hostname: hostname || urlDomain, + browser, + os, + device, + screen, + language, + country, + subdivision1, + subdivision2, + city, + tag, + }); } - await saveEvent({ - websiteId, - sessionId, - visitId, - urlPath, - urlQuery, - referrerPath, - referrerQuery, - referrerDomain, - pageTitle: title, - eventName: name, - eventData: data, - hostname: hostname || urlDomain, - browser, - os, - device, - screen, - language, - country, - subdivision1, - subdivision2, - city, - tag, - }); - } + if (type === COLLECTION_TYPE.identify) { + if (!data) { + return badRequest('Data required.'); + } - if (type === COLLECTION_TYPE.identify) { - if (!data) { - return badRequest('Data required.'); + await saveSessionData({ + websiteId, + sessionId, + sessionData: data, + }); } - await saveSessionData({ - websiteId, - sessionId, - sessionData: data, - }); + const token = createToken({ websiteId, sessionId, visitId, iat }, secret()); + + return json({ cache: token }); + } catch (e) { + return serverError(e); } - - const token = createToken({ websiteId, sessionId, visitId, iat }, secret()); - - return json({ cache: token }); }