diff --git a/apps/frontend/src/composables/fetch.js b/apps/frontend/src/composables/fetch.js index b7a634a0d..6533fb1ce 100644 --- a/apps/frontend/src/composables/fetch.js +++ b/apps/frontend/src/composables/fetch.js @@ -3,9 +3,10 @@ * This composable is kept for legacy code that hasn't been migrated yet. */ +import { withLabrinthCanaryHeader } from '~/helpers/canary.ts' + let cachedRateLimitKey = undefined let rateLimitKeyPromise = undefined -const LABRINTH_CANARY_COOKIE = 'labrinth-canary=always' async function getRateLimitKey(config) { if (config.rateLimitKey) return config.rateLimitKey @@ -35,19 +36,12 @@ export const useBaseFetch = async (url, options = {}, skipAuth = false) => { options.headers = {} } + options.headers = withLabrinthCanaryHeader(options.headers) + if (import.meta.server) { options.headers['x-ratelimit-key'] = await getRateLimitKey(config) } - if (useFeatureFlags().value.labrinthApiCanary) { - const existingCookie = options.headers.cookie - if (!existingCookie?.split('; ').includes(LABRINTH_CANARY_COOKIE)) { - options.headers.cookie = existingCookie - ? `${existingCookie}; ${LABRINTH_CANARY_COOKIE}` - : LABRINTH_CANARY_COOKIE - } - } - if (!skipAuth) { const auth = await useAuth() diff --git a/apps/frontend/src/helpers/api.ts b/apps/frontend/src/helpers/api.ts index 7b659edcb..5b49bcf3c 100644 --- a/apps/frontend/src/helpers/api.ts +++ b/apps/frontend/src/helpers/api.ts @@ -2,9 +2,7 @@ import { type AbstractFeature, type AuthConfig, AuthFeature, - CanaryCookieFeature, CircuitBreakerFeature, - LABRINTH_CANARY_COOKIE, NodeAuthFeature, nodeAuthState, NuxtCircuitBreakerStorage, @@ -30,11 +28,7 @@ export function createModrinthClient( auth: Ref<{ token: string | undefined }>, config: { apiBaseUrl: string; archonBaseUrl: string; rateLimitKey?: string }, ): NuxtModrinthClient { - const flags = useFeatureFlags() const optionalFeatures = [ - new CanaryCookieFeature({ - getCookie: () => (flags.value.labrinthApiCanary ? LABRINTH_CANARY_COOKIE : undefined), - }) as AbstractFeature, import.meta.dev ? (new VerboseLoggingFeature() as AbstractFeature) : undefined, ].filter(Boolean) as AbstractFeature[] diff --git a/apps/frontend/src/helpers/canary.ts b/apps/frontend/src/helpers/canary.ts new file mode 100644 index 000000000..5ad0ebeca --- /dev/null +++ b/apps/frontend/src/helpers/canary.ts @@ -0,0 +1,15 @@ +export const LABRINTH_CANARY_HEADER = 'Labrinth-Canary' +export const LABRINTH_CANARY_VALUE = 'always' + +export function withLabrinthCanaryHeader(headers: Record = {}) { + const flags = useFeatureFlags() + + if (!flags.value.labrinthApiCanary) { + return headers + } + + return { + ...headers, + [LABRINTH_CANARY_HEADER]: LABRINTH_CANARY_VALUE, + } +} diff --git a/apps/frontend/src/middleware/project.global.ts b/apps/frontend/src/middleware/project.global.ts index d18a72b21..0bba2ea3e 100644 --- a/apps/frontend/src/middleware/project.global.ts +++ b/apps/frontend/src/middleware/project.global.ts @@ -25,11 +25,7 @@ export default defineNuxtRouteMiddleware(async (to) => { const queryClient = useAppQueryClient() const authToken = useCookie('auth-token') - const flags = useFeatureFlags() - const client = useServerModrinthClient({ - authToken: authToken.value || undefined, - canaryCookie: flags.value.labrinthApiCanary, - }) + const client = useServerModrinthClient({ authToken: authToken.value || undefined }) const tags = useGeneratedState() const projectId = to.params.id as string diff --git a/apps/frontend/src/pages/discover/[type]/index.vue b/apps/frontend/src/pages/discover/[type]/index.vue index 4adbafb14..438b539a3 100644 --- a/apps/frontend/src/pages/discover/[type]/index.vue +++ b/apps/frontend/src/pages/discover/[type]/index.vue @@ -47,6 +47,7 @@ import LogoAnimated from '~/components/brand/LogoAnimated.vue' import AdPlaceholder from '~/components/ui/AdPlaceholder.vue' import { projectQueryOptions } from '~/composables/queries/project' import { versionQueryOptions } from '~/composables/queries/version' +import { withLabrinthCanaryHeader } from '~/helpers/canary.ts' import type { DisplayLocation, DisplayMode } from '~/plugins/cosmetics.ts' const { formatMessage } = useVIntl() @@ -472,6 +473,7 @@ const { return url }, { + headers: computed(() => withLabrinthCanaryHeader()), watch: false, transform: (hits) => { debug('useLazyFetch transform, hits:', (hits as any)?.total_hits) diff --git a/apps/frontend/src/server/utils/api-client.ts b/apps/frontend/src/server/utils/api-client.ts index 93c4e0eb7..0352ddb8e 100644 --- a/apps/frontend/src/server/utils/api-client.ts +++ b/apps/frontend/src/server/utils/api-client.ts @@ -1,9 +1,7 @@ import { type AuthConfig, AuthFeature, - CanaryCookieFeature, type FeatureConfig, - LABRINTH_CANARY_COOKIE, type NuxtClientConfig, NuxtModrinthClient, } from '@modrinth/api-client' @@ -22,7 +20,6 @@ async function getRateLimitKeyFromSecretsStore(): Promise { export interface ServerModrinthClientOptions { event?: H3Event authToken?: string - canaryCookie?: boolean } export function useServerModrinthClient(options?: ServerModrinthClientOptions): NuxtModrinthClient { @@ -40,10 +37,6 @@ export function useServerModrinthClient(options?: ServerModrinthClientOptions): ) } - if (options?.canaryCookie) { - features.push(new CanaryCookieFeature({ getCookie: () => LABRINTH_CANARY_COOKIE })) - } - const clientConfig: NuxtClientConfig = { labrinthBaseUrl: apiBaseUrl, rateLimitKey: config.rateLimitKey || getRateLimitKeyFromSecretsStore, diff --git a/packages/api-client/src/features/canary-cookie.ts b/packages/api-client/src/features/canary-cookie.ts deleted file mode 100644 index e98719579..000000000 --- a/packages/api-client/src/features/canary-cookie.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { AbstractFeature, type FeatureConfig } from '../core/abstract-feature' - -export const LABRINTH_CANARY_COOKIE = 'labrinth-canary=always' - -export interface CanaryCookieConfig extends FeatureConfig { - getCookie?: () => string | undefined | Promise -} - -export class CanaryCookieFeature extends AbstractFeature { - declare protected config: CanaryCookieConfig - - constructor(config?: CanaryCookieConfig) { - super(config) - } - - shouldApply(context: Parameters[0]): boolean { - return super.shouldApply(context) && context.options.api === 'labrinth' - } - - async execute(next: () => Promise, context: Parameters[1]) { - const cookie = this.config.getCookie ? await this.config.getCookie() : LABRINTH_CANARY_COOKIE - if (!cookie) { - return next() - } - - const headers = { ...(context.options.headers ?? {}) } - const existingCookie = headers.cookie ?? headers.Cookie - - if (!existingCookie?.split('; ').includes(cookie)) { - headers.cookie = existingCookie ? `${existingCookie}; ${cookie}` : cookie - delete headers.Cookie - context.options.headers = headers - } - - return next() - } -} diff --git a/packages/api-client/src/index.ts b/packages/api-client/src/index.ts index 1c48c332d..fdb802506 100644 --- a/packages/api-client/src/index.ts +++ b/packages/api-client/src/index.ts @@ -9,11 +9,6 @@ export { } from './core/abstract-websocket' export { ModrinthApiError, ModrinthServerError } from './core/errors' export { type AuthConfig, AuthFeature } from './features/auth' -export { - type CanaryCookieConfig, - CanaryCookieFeature, - LABRINTH_CANARY_COOKIE, -} from './features/canary-cookie' export { type CircuitBreakerConfig, CircuitBreakerFeature,