From c5af5302a190f6e9267eab60280a5c9295676e0b Mon Sep 17 00:00:00 2001 From: manchenkoff Date: Tue, 1 Oct 2024 16:34:58 +0200 Subject: [PATCH] fix: prevent concurrent update of request headers --- src/runtime/interceptors/common/request.ts | 9 +++--- src/runtime/interceptors/cookie/request.ts | 33 +++++++++------------- src/runtime/interceptors/token/request.ts | 5 +++- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/runtime/interceptors/common/request.ts b/src/runtime/interceptors/common/request.ts index 7d72f24..7bc8abb 100644 --- a/src/runtime/interceptors/common/request.ts +++ b/src/runtime/interceptors/common/request.ts @@ -15,11 +15,10 @@ export default async function handleRequestHeaders( ): Promise { const method = ctx.options.method?.toLowerCase() ?? 'get' - if (!ctx.options.headers) { - ctx.options.headers = {} - } - - Object.assign(ctx.options.headers!, { Accept: 'application/json' }) + ctx.options.headers = Object.assign( + ctx.options.headers || {}, + { Accept: 'application/json' }, + ) // https://laravel.com/docs/10.x/routing#form-method-spoofing if (method === 'put' && ctx.options.body instanceof FormData) { diff --git a/src/runtime/interceptors/cookie/request.ts b/src/runtime/interceptors/cookie/request.ts index 2361a36..ba6af11 100644 --- a/src/runtime/interceptors/cookie/request.ts +++ b/src/runtime/interceptors/cookie/request.ts @@ -2,12 +2,7 @@ import type { FetchContext } from 'ofetch' import type { ConsolaInstance } from 'consola' import { useSanctumConfig } from '../../composables/useSanctumConfig' import type { ModuleOptions } from '../../types/options' -import { - useCookie, - useRequestHeaders, - useRequestURL, - type NuxtApp, -} from '#app' +import { type NuxtApp, useCookie, useRequestHeaders, useRequestURL } from '#app' const SECURE_METHODS = new Set(['post', 'delete', 'put', 'patch']) const COOKIE_OPTIONS: { readonly: true } = { readonly: true } @@ -17,15 +12,15 @@ const COOKIE_OPTIONS: { readonly: true } = { readonly: true } * @param headers Headers collection to extend * @param config Module configuration */ -function appendServerHeaders( - headers: HeadersInit, +function useServerHeaders( + headers: HeadersInit | undefined, config: ModuleOptions, -): void { +): HeadersInit { const clientHeaders = useRequestHeaders(['cookie', 'user-agent']) const origin = config.origin ?? useRequestURL().origin - Object.assign( - headers, + return Object.assign( + headers || {}, { Referer: origin, Origin: origin, @@ -60,10 +55,10 @@ async function initCsrfCookie( * @param logger Logger instance */ async function useCsrfHeader( - headers: HeadersInit, + headers: HeadersInit | undefined, config: ModuleOptions, logger: ConsolaInstance, -): Promise { +): Promise { let csrfToken = useCookie(config.csrf.cookie!, COOKIE_OPTIONS) if (!csrfToken.value) { @@ -77,13 +72,13 @@ async function useCsrfHeader( `${config.csrf.cookie} cookie is missing, unable to set ${config.csrf.header} header`, ) - return + return headers || {} } logger.debug(`Added ${config.csrf.header} header to pass to the API`) - Object.assign( - headers, + return Object.assign( + headers || {}, { [config.csrf.header!]: csrfToken.value }, ) } @@ -102,12 +97,12 @@ export default async function handleRequestCookies( const method = ctx.options.method?.toLowerCase() ?? 'get' if (import.meta.server) { - appendServerHeaders(ctx.options.headers!, config) + ctx.options.headers = useServerHeaders(ctx.options.headers, config) } if (SECURE_METHODS.has(method)) { - await useCsrfHeader( - ctx.options.headers!, + ctx.options.headers = await useCsrfHeader( + ctx.options.headers, config, logger, ) diff --git a/src/runtime/interceptors/token/request.ts b/src/runtime/interceptors/token/request.ts index c2f4585..66f4ed8 100644 --- a/src/runtime/interceptors/token/request.ts +++ b/src/runtime/interceptors/token/request.ts @@ -23,7 +23,10 @@ export default async function handleRequestTokenHeader( return } - Object.assign(ctx.options.headers!, { Authorization: `Bearer ${token}` }) + ctx.options.headers = Object.assign( + ctx.options.headers || {}, + { Authorization: `Bearer ${token}` }, + ) logger.debug( '[handleRequestTokenHeader] headers modified',