Revert last canary flag PR and use a better method (#5535)
* Revert "Implement Labrinth Canary API flag (#5531)"
This reverts commit 3b21944a75.
* Use Labrinth-Canary header instead of cookie for API canary
* prepr
* fix rebase
This commit is contained in:
@@ -3,9 +3,10 @@
|
|||||||
* This composable is kept for legacy code that hasn't been migrated yet.
|
* This composable is kept for legacy code that hasn't been migrated yet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { withLabrinthCanaryHeader } from '~/helpers/canary.ts'
|
||||||
|
|
||||||
let cachedRateLimitKey = undefined
|
let cachedRateLimitKey = undefined
|
||||||
let rateLimitKeyPromise = undefined
|
let rateLimitKeyPromise = undefined
|
||||||
const LABRINTH_CANARY_COOKIE = 'labrinth-canary=always'
|
|
||||||
|
|
||||||
async function getRateLimitKey(config) {
|
async function getRateLimitKey(config) {
|
||||||
if (config.rateLimitKey) return config.rateLimitKey
|
if (config.rateLimitKey) return config.rateLimitKey
|
||||||
@@ -35,19 +36,12 @@ export const useBaseFetch = async (url, options = {}, skipAuth = false) => {
|
|||||||
options.headers = {}
|
options.headers = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options.headers = withLabrinthCanaryHeader(options.headers)
|
||||||
|
|
||||||
if (import.meta.server) {
|
if (import.meta.server) {
|
||||||
options.headers['x-ratelimit-key'] = await getRateLimitKey(config)
|
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) {
|
if (!skipAuth) {
|
||||||
const auth = await useAuth()
|
const auth = await useAuth()
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import {
|
|||||||
type AbstractFeature,
|
type AbstractFeature,
|
||||||
type AuthConfig,
|
type AuthConfig,
|
||||||
AuthFeature,
|
AuthFeature,
|
||||||
CanaryCookieFeature,
|
|
||||||
CircuitBreakerFeature,
|
CircuitBreakerFeature,
|
||||||
LABRINTH_CANARY_COOKIE,
|
|
||||||
NodeAuthFeature,
|
NodeAuthFeature,
|
||||||
nodeAuthState,
|
nodeAuthState,
|
||||||
NuxtCircuitBreakerStorage,
|
NuxtCircuitBreakerStorage,
|
||||||
@@ -30,11 +28,7 @@ export function createModrinthClient(
|
|||||||
auth: Ref<{ token: string | undefined }>,
|
auth: Ref<{ token: string | undefined }>,
|
||||||
config: { apiBaseUrl: string; archonBaseUrl: string; rateLimitKey?: string },
|
config: { apiBaseUrl: string; archonBaseUrl: string; rateLimitKey?: string },
|
||||||
): NuxtModrinthClient {
|
): NuxtModrinthClient {
|
||||||
const flags = useFeatureFlags()
|
|
||||||
const optionalFeatures = [
|
const optionalFeatures = [
|
||||||
new CanaryCookieFeature({
|
|
||||||
getCookie: () => (flags.value.labrinthApiCanary ? LABRINTH_CANARY_COOKIE : undefined),
|
|
||||||
}) as AbstractFeature,
|
|
||||||
import.meta.dev ? (new VerboseLoggingFeature() as AbstractFeature) : undefined,
|
import.meta.dev ? (new VerboseLoggingFeature() as AbstractFeature) : undefined,
|
||||||
].filter(Boolean) as AbstractFeature[]
|
].filter(Boolean) as AbstractFeature[]
|
||||||
|
|
||||||
|
|||||||
15
apps/frontend/src/helpers/canary.ts
Normal file
15
apps/frontend/src/helpers/canary.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
export const LABRINTH_CANARY_HEADER = 'Labrinth-Canary'
|
||||||
|
export const LABRINTH_CANARY_VALUE = 'always'
|
||||||
|
|
||||||
|
export function withLabrinthCanaryHeader(headers: Record<string, string> = {}) {
|
||||||
|
const flags = useFeatureFlags()
|
||||||
|
|
||||||
|
if (!flags.value.labrinthApiCanary) {
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...headers,
|
||||||
|
[LABRINTH_CANARY_HEADER]: LABRINTH_CANARY_VALUE,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,11 +25,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
|||||||
|
|
||||||
const queryClient = useAppQueryClient()
|
const queryClient = useAppQueryClient()
|
||||||
const authToken = useCookie('auth-token')
|
const authToken = useCookie('auth-token')
|
||||||
const flags = useFeatureFlags()
|
const client = useServerModrinthClient({ authToken: authToken.value || undefined })
|
||||||
const client = useServerModrinthClient({
|
|
||||||
authToken: authToken.value || undefined,
|
|
||||||
canaryCookie: flags.value.labrinthApiCanary,
|
|
||||||
})
|
|
||||||
const tags = useGeneratedState()
|
const tags = useGeneratedState()
|
||||||
const projectId = to.params.id as string
|
const projectId = to.params.id as string
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import LogoAnimated from '~/components/brand/LogoAnimated.vue'
|
|||||||
import AdPlaceholder from '~/components/ui/AdPlaceholder.vue'
|
import AdPlaceholder from '~/components/ui/AdPlaceholder.vue'
|
||||||
import { projectQueryOptions } from '~/composables/queries/project'
|
import { projectQueryOptions } from '~/composables/queries/project'
|
||||||
import { versionQueryOptions } from '~/composables/queries/version'
|
import { versionQueryOptions } from '~/composables/queries/version'
|
||||||
|
import { withLabrinthCanaryHeader } from '~/helpers/canary.ts'
|
||||||
import type { DisplayLocation, DisplayMode } from '~/plugins/cosmetics.ts'
|
import type { DisplayLocation, DisplayMode } from '~/plugins/cosmetics.ts'
|
||||||
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
@@ -472,6 +473,7 @@ const {
|
|||||||
return url
|
return url
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
headers: computed(() => withLabrinthCanaryHeader()),
|
||||||
watch: false,
|
watch: false,
|
||||||
transform: (hits) => {
|
transform: (hits) => {
|
||||||
debug('useLazyFetch transform, hits:', (hits as any)?.total_hits)
|
debug('useLazyFetch transform, hits:', (hits as any)?.total_hits)
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
type AuthConfig,
|
type AuthConfig,
|
||||||
AuthFeature,
|
AuthFeature,
|
||||||
CanaryCookieFeature,
|
|
||||||
type FeatureConfig,
|
type FeatureConfig,
|
||||||
LABRINTH_CANARY_COOKIE,
|
|
||||||
type NuxtClientConfig,
|
type NuxtClientConfig,
|
||||||
NuxtModrinthClient,
|
NuxtModrinthClient,
|
||||||
} from '@modrinth/api-client'
|
} from '@modrinth/api-client'
|
||||||
@@ -22,7 +20,6 @@ async function getRateLimitKeyFromSecretsStore(): Promise<string | undefined> {
|
|||||||
export interface ServerModrinthClientOptions {
|
export interface ServerModrinthClientOptions {
|
||||||
event?: H3Event
|
event?: H3Event
|
||||||
authToken?: string
|
authToken?: string
|
||||||
canaryCookie?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useServerModrinthClient(options?: ServerModrinthClientOptions): NuxtModrinthClient {
|
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 = {
|
const clientConfig: NuxtClientConfig = {
|
||||||
labrinthBaseUrl: apiBaseUrl,
|
labrinthBaseUrl: apiBaseUrl,
|
||||||
rateLimitKey: config.rateLimitKey || getRateLimitKeyFromSecretsStore,
|
rateLimitKey: config.rateLimitKey || getRateLimitKeyFromSecretsStore,
|
||||||
|
|||||||
@@ -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<string | undefined>
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CanaryCookieFeature extends AbstractFeature {
|
|
||||||
declare protected config: CanaryCookieConfig
|
|
||||||
|
|
||||||
constructor(config?: CanaryCookieConfig) {
|
|
||||||
super(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldApply(context: Parameters<AbstractFeature['shouldApply']>[0]): boolean {
|
|
||||||
return super.shouldApply(context) && context.options.api === 'labrinth'
|
|
||||||
}
|
|
||||||
|
|
||||||
async execute<T>(next: () => Promise<T>, context: Parameters<AbstractFeature['execute']>[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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,11 +9,6 @@ export {
|
|||||||
} from './core/abstract-websocket'
|
} from './core/abstract-websocket'
|
||||||
export { ModrinthApiError, ModrinthServerError } from './core/errors'
|
export { ModrinthApiError, ModrinthServerError } from './core/errors'
|
||||||
export { type AuthConfig, AuthFeature } from './features/auth'
|
export { type AuthConfig, AuthFeature } from './features/auth'
|
||||||
export {
|
|
||||||
type CanaryCookieConfig,
|
|
||||||
CanaryCookieFeature,
|
|
||||||
LABRINTH_CANARY_COOKIE,
|
|
||||||
} from './features/canary-cookie'
|
|
||||||
export {
|
export {
|
||||||
type CircuitBreakerConfig,
|
type CircuitBreakerConfig,
|
||||||
CircuitBreakerFeature,
|
CircuitBreakerFeature,
|
||||||
|
|||||||
Reference in New Issue
Block a user