mirror of
https://github.com/umami-software/umami.git
synced 2026-02-16 10:35:35 +01:00
Return server error.
This commit is contained in:
parent
4d6ec631f7
commit
6466cef269
2 changed files with 146 additions and 142 deletions
|
|
@ -31,7 +31,7 @@ export async function POST(request: Request) {
|
||||||
|
|
||||||
const { id, role, createdAt } = user;
|
const { id, role, createdAt } = user;
|
||||||
|
|
||||||
let token = null;
|
let token: string;
|
||||||
|
|
||||||
if (redis.enabled) {
|
if (redis.enabled) {
|
||||||
token = await saveAuth({ userId: id, role });
|
token = await saveAuth({ userId: id, role });
|
||||||
|
|
|
||||||
|
|
@ -29,170 +29,174 @@ const schema = z.object({
|
||||||
});
|
});
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
// Bot check
|
try {
|
||||||
if (!process.env.DISABLE_BOT_CHECK && isbot(request.headers.get('user-agent'))) {
|
// Bot check
|
||||||
return json({ beep: 'boop' });
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Find website
|
const { body, error } = await parseRequest(request, schema, { skipAuth: true });
|
||||||
if (!cache?.websiteId) {
|
|
||||||
const website = await fetchWebsite(websiteId);
|
|
||||||
|
|
||||||
if (!website) {
|
if (error) {
|
||||||
return badRequest('Website not found.');
|
return error();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Client info
|
const { type, payload } = body;
|
||||||
const { ip, userAgent, device, browser, os, country, subdivision1, subdivision2, city } =
|
|
||||||
await getClientInfo(request, payload);
|
|
||||||
|
|
||||||
// IP block
|
const {
|
||||||
if (hasBlockedIp(ip)) {
|
website: websiteId,
|
||||||
return forbidden();
|
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 (cacheHeader) {
|
||||||
if (!clickhouse.enabled && !cache?.sessionId) {
|
const result = await parseToken(cacheHeader, secret());
|
||||||
const session = await fetchSession(websiteId, sessionId);
|
|
||||||
|
|
||||||
// Create a session if not found
|
if (result) {
|
||||||
if (!session) {
|
cache = result;
|
||||||
try {
|
}
|
||||||
await createSession({
|
}
|
||||||
id: sessionId,
|
|
||||||
websiteId,
|
// Find website
|
||||||
hostname,
|
if (!cache?.websiteId) {
|
||||||
browser,
|
const website = await fetchWebsite(websiteId);
|
||||||
os,
|
|
||||||
device,
|
if (!website) {
|
||||||
screen,
|
return badRequest('Website not found.');
|
||||||
language,
|
}
|
||||||
country,
|
}
|
||||||
subdivision1,
|
|
||||||
subdivision2,
|
// Client info
|
||||||
city,
|
const { ip, userAgent, device, browser, os, country, subdivision1, subdivision2, city } =
|
||||||
});
|
await getClientInfo(request, payload);
|
||||||
} catch (e: any) {
|
|
||||||
if (!e.message.toLowerCase().includes('unique constraint')) {
|
// IP block
|
||||||
return serverError(e);
|
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
|
// Visit info
|
||||||
const now = Math.floor(new Date().getTime() / 1000);
|
const now = Math.floor(new Date().getTime() / 1000);
|
||||||
let visitId = cache?.visitId || uuid(sessionId, visitSalt());
|
let visitId = cache?.visitId || uuid(sessionId, visitSalt());
|
||||||
let iat = cache?.iat || now;
|
let iat = cache?.iat || now;
|
||||||
|
|
||||||
// Expire visit after 30 minutes
|
// Expire visit after 30 minutes
|
||||||
if (now - iat > 1800) {
|
if (now - iat > 1800) {
|
||||||
visitId = uuid(sessionId, visitSalt());
|
visitId = uuid(sessionId, visitSalt());
|
||||||
iat = now;
|
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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let referrerPath: string;
|
if (type === COLLECTION_TYPE.event) {
|
||||||
let referrerQuery: string;
|
const base = hostname ? `http://${hostname}` : 'http://localhost';
|
||||||
let referrerDomain: string;
|
const currentUrl = new URL(url, base);
|
||||||
|
|
||||||
if (referrer) {
|
let urlPath = currentUrl.pathname;
|
||||||
const referrerUrl = new URL(referrer, base);
|
const urlQuery = currentUrl.search.substring(1);
|
||||||
|
const urlDomain = currentUrl.hostname.replace(/^www./, '');
|
||||||
|
|
||||||
referrerPath = referrerUrl.pathname;
|
if (process.env.REMOVE_TRAILING_SLASH) {
|
||||||
referrerQuery = referrerUrl.search.substring(1);
|
urlPath = urlPath.replace(/(.+)\/$/, '$1');
|
||||||
|
|
||||||
if (referrerUrl.hostname !== 'localhost') {
|
|
||||||
referrerDomain = referrerUrl.hostname.replace(/^www\./, '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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({
|
if (type === COLLECTION_TYPE.identify) {
|
||||||
websiteId,
|
if (!data) {
|
||||||
sessionId,
|
return badRequest('Data required.');
|
||||||
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) {
|
await saveSessionData({
|
||||||
if (!data) {
|
websiteId,
|
||||||
return badRequest('Data required.');
|
sessionId,
|
||||||
|
sessionData: data,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await saveSessionData({
|
const token = createToken({ websiteId, sessionId, visitId, iat }, secret());
|
||||||
websiteId,
|
|
||||||
sessionId,
|
return json({ cache: token });
|
||||||
sessionData: data,
|
} catch (e) {
|
||||||
});
|
return serverError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = createToken({ websiteId, sessionId, visitId, iat }, secret());
|
|
||||||
|
|
||||||
return json({ cache: token });
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue