mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
Small fixes
This commit is contained in:
parent
05b63058c4
commit
bb293c802f
@ -1,5 +1,14 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { parseAndValidateConfig } from './route';
|
||||
import { getDefaultEntriesForRequest, parseAndValidateConfig } from './route';
|
||||
|
||||
function reqForHost(host: string, forwardedHost?: string) {
|
||||
return {
|
||||
headers: {
|
||||
host: [host],
|
||||
...(forwardedHost ? { "x-forwarded-host": [forwardedHost] } : {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe('parseAndValidateConfig', () => {
|
||||
it('should parse a single entry with probability 1', () => {
|
||||
@ -66,3 +75,44 @@ describe('parseAndValidateConfig', () => {
|
||||
expect(() => parseAndValidateConfig({ "1": "https://api.hexclave.com" })).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefaultEntriesForRequest', () => {
|
||||
it('keeps legacy Stack Auth requests on Stack Auth API fallbacks', () => {
|
||||
expect(getDefaultEntriesForRequest(reqForHost("api.stack-auth.com"))).toEqual([
|
||||
{
|
||||
probability: 1,
|
||||
urls: [
|
||||
"https://api.stack-auth.com",
|
||||
"https://api1.stack-auth.com",
|
||||
"https://api2.stack-auth.com",
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps Hexclave requests on Hexclave API fallbacks', () => {
|
||||
expect(getDefaultEntriesForRequest(reqForHost("api.hexclave.com"))).toEqual([
|
||||
{
|
||||
probability: 1,
|
||||
urls: [
|
||||
"https://api.hexclave.com",
|
||||
"https://api1.hexclave.com",
|
||||
"https://api2.hexclave.com",
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('maps fallback hosts back to the same brand canonical API host', () => {
|
||||
expect(getDefaultEntriesForRequest(reqForHost("api2.stack-auth.com"))[0].urls[0]).toBe("https://api.stack-auth.com");
|
||||
expect(getDefaultEntriesForRequest(reqForHost("api2.hexclave.com"))[0].urls[0]).toBe("https://api.hexclave.com");
|
||||
});
|
||||
|
||||
it('prefers x-forwarded-host over host when selecting the brand', () => {
|
||||
expect(getDefaultEntriesForRequest(reqForHost("api.stack-auth.com", "api.hexclave.com"))[0].urls).toEqual([
|
||||
"https://api.hexclave.com",
|
||||
"https://api1.hexclave.com",
|
||||
"https://api2.hexclave.com",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { createSmartRouteHandler } from "@/route-handlers/smart-route-handler";
|
||||
import { getApiUrlForRequest } from "@/lib/request-api-url";
|
||||
import { urlSchema, yupArray, yupNumber, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields";
|
||||
import { HexclaveAssertionError } from "@stackframe/stack-shared/dist/utils/errors";
|
||||
import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env";
|
||||
import { getDefaultApiUrls } from "@stackframe/stack-shared/dist/utils/urls";
|
||||
|
||||
/**
|
||||
* Env var format: JSON object mapping probability (as string number) to URL arrays.
|
||||
@ -44,24 +44,47 @@ export function parseAndValidateConfig(raw: unknown): Array<{ probability: numbe
|
||||
}
|
||||
|
||||
let cachedEntries: ReturnType<typeof parseAndValidateConfig> | undefined;
|
||||
function getCachedConfig() {
|
||||
function getConfiguredEntries() {
|
||||
if (!cachedEntries) {
|
||||
const rawEnv = getEnvVariable("STACK_BACKEND_URLS_CONFIG", "");
|
||||
if (rawEnv) {
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(rawEnv);
|
||||
} catch (e) {
|
||||
throw new HexclaveAssertionError(`STACK_BACKEND_URLS_CONFIG is not valid JSON: ${e}`);
|
||||
}
|
||||
cachedEntries = parseAndValidateConfig(parsed);
|
||||
} else {
|
||||
cachedEntries = [{ probability: 1, urls: getDefaultApiUrls(getEnvVariable("NEXT_PUBLIC_STACK_API_URL")) }];
|
||||
if (!rawEnv) {
|
||||
return undefined;
|
||||
}
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(rawEnv);
|
||||
} catch (e) {
|
||||
throw new HexclaveAssertionError(`STACK_BACKEND_URLS_CONFIG is not valid JSON: ${e}`);
|
||||
}
|
||||
cachedEntries = parseAndValidateConfig(parsed);
|
||||
}
|
||||
return cachedEntries;
|
||||
}
|
||||
|
||||
function getDefaultBackendUrls(primaryBaseUrl: string): string[] {
|
||||
if (primaryBaseUrl === "https://api.stack-auth.com") {
|
||||
return ["https://api.stack-auth.com", "https://api1.stack-auth.com", "https://api2.stack-auth.com"];
|
||||
}
|
||||
if (primaryBaseUrl === "https://api.dev.stack-auth.com") {
|
||||
return ["https://api.dev.stack-auth.com", "https://api1.dev.stack-auth.com", "https://api2.dev.stack-auth.com"];
|
||||
}
|
||||
if (primaryBaseUrl === "https://api.hexclave.com") {
|
||||
return ["https://api.hexclave.com", "https://api1.hexclave.com", "https://api2.hexclave.com"];
|
||||
}
|
||||
if (primaryBaseUrl === "https://api.dev.hexclave.com") {
|
||||
return ["https://api.dev.hexclave.com", "https://api1.dev.hexclave.com", "https://api2.dev.hexclave.com"];
|
||||
}
|
||||
const localhostMatch = primaryBaseUrl.match(/^http:\/\/localhost:(\d+)02$/);
|
||||
if (localhostMatch) {
|
||||
return [primaryBaseUrl, `http://localhost:${localhostMatch[1]}10`];
|
||||
}
|
||||
return [primaryBaseUrl];
|
||||
}
|
||||
|
||||
export function getDefaultEntriesForRequest(req: { headers: Record<string, string[] | undefined> }): ReturnType<typeof parseAndValidateConfig> {
|
||||
return [{ probability: 1, urls: getDefaultBackendUrls(getApiUrlForRequest(req)) }];
|
||||
}
|
||||
|
||||
export const GET = createSmartRouteHandler({
|
||||
metadata: {
|
||||
hidden: true,
|
||||
@ -79,8 +102,8 @@ export const GET = createSmartRouteHandler({
|
||||
urls: yupArray(yupString().defined()).defined(),
|
||||
}).defined(),
|
||||
}),
|
||||
handler: async () => {
|
||||
const entries = getCachedConfig();
|
||||
handler: async (_req, fullReq) => {
|
||||
const entries = getConfiguredEntries() ?? getDefaultEntriesForRequest(fullReq);
|
||||
|
||||
const roll = Math.random();
|
||||
let cumulative = 0;
|
||||
|
||||
@ -34,6 +34,7 @@ const corsAllowedRequestHeaders = [
|
||||
// User auth
|
||||
'x-stack-refresh-token',
|
||||
'x-stack-access-token',
|
||||
'x-stack-allow-restricted-user',
|
||||
'x-stack-allow-anonymous-user',
|
||||
|
||||
// Sentry
|
||||
|
||||
Loading…
Reference in New Issue
Block a user