Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions src/assets.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import fsp from 'node:fs/promises'
import { writeFileSync } from 'node:fs'
import { addDevServerHandler, addVitePlugin, useNuxt } from '@nuxt/kit'
import { addDevServerHandler, addVitePlugin, useNuxt, isNuxtMajorVersion } from '@nuxt/kit'
import type { H3Event } from 'h3'
import { eventHandler, createEvent, createError, setResponseHeader } from 'h3'
import { $fetch } from 'ofetch'
import { colors } from 'consola/utils'
import { defu } from 'defu'
import type { NitroConfig } from 'nitropack'
import { joinURL } from 'ufo'
import { join } from 'pathe'
import { join, basename } from 'pathe'

import { normalizeFontData } from 'fontless'
import type { NormalizeFontDataContext } from 'fontless'
Expand All @@ -20,6 +20,9 @@ import type { ModuleOptions } from './types'
export async function setupPublicAssetStrategy(options: ModuleOptions['assets'] = {}) {
const nuxt = useNuxt()

// @ts-expect-error 5 cannot satisfy 2 | 3 | 4
const isNuxt5 = isNuxtMajorVersion(5, nuxt)

const context: NormalizeFontDataContext = {
dev: nuxt.options.dev,
renderedFontURLs: new Map<string, string>(),
Expand All @@ -29,8 +32,8 @@ export async function setupPublicAssetStrategy(options: ModuleOptions['assets']

// Register font proxy URL for development
async function devEventHandler(event: H3Event) {
const filename = event.path.slice(1)
const url = context.renderedFontURLs.get(event.path.slice(1))
const filename = basename(event.path)
const url = context.renderedFontURLs.get(filename)
Comment on lines +35 to +36

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does h3's event.path getter include the query string from the request URL?

💡 Result:

Yes, the event.path getter in h3 includes the query string from the request URL [1]. In H3, event.path provides the full path of the incoming request, including both the path and the query parameters (for example, "/test?test=123") [1]. However, please note that event.path is deprecated in H3 v2 [2]. It is recommended to use event.url.pathname and event.url.search instead to access the path and query string components separately [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant file and nearby context.
git ls-files src/assets.ts
wc -l src/assets.ts
cat -n src/assets.ts | sed -n '1,220p'

Repository: nuxt/fonts

Length of output: 6001


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for related path handling and any existing normalization helpers.
rg -n "basename\\(|event\\.path|renderedFontURLs|assetsBaseURL|pathname|search" src

Repository: nuxt/fonts

Length of output: 874


Strip query strings before deriving the font filename. event.path includes the search string in h3, so basename(event.path) will miss cached entries for requests like font.woff2?v=1 and 404. Use event.url.pathname (or strip event.url.search) here instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/assets.ts` around lines 32 - 33, The font lookup in the assets handler is
using event.path directly, so query strings from h3 requests can make
basename(...) miss cached entries and cause false 404s. Update the logic in the
assets.ts flow around the filename/url lookup to derive the name from
event.url.pathname, or otherwise strip event.url.search before calling basename,
so renderedFontURLs keys match requests like font.woff2?v=1.

if (!url) {
throw createError({ statusCode: 404 })
}
Expand All @@ -47,7 +50,9 @@ export async function setupPublicAssetStrategy(options: ModuleOptions['assets']
}

addDevServerHandler({
route: joinURL(nuxt.options.runtimeConfig.app.baseURL || nuxt.options.app.baseURL, context.assetsBaseURL),
route: isNuxt5
? joinURL(nuxt.options.runtimeConfig.app.baseURL || nuxt.options.app.baseURL, context.assetsBaseURL, '**')
: joinURL(nuxt.options.runtimeConfig.app.baseURL || nuxt.options.app.baseURL, context.assetsBaseURL),
handler: eventHandler(devEventHandler),
})

Expand Down Expand Up @@ -89,6 +94,7 @@ export async function setupPublicAssetStrategy(options: ModuleOptions['assets']
dir: cacheDir,
maxAge: ONE_YEAR_IN_SECONDS,
baseURL: context.assetsBaseURL,
fallthrough: nuxt.options.dev,
}],
ignore: [`!${join(cacheDir, '**/*')}`],
prerender: {
Expand Down
Loading