Skip to content

Let ParamMatcher functions return a string to redirect  #8289

@darrylyeo

Description

@darrylyeo

Describe the problem

Routes with parameters don't have an easy way to redirect to a "canonical" route, and param matchers are too strict (invalid routes will just 404).

Describe the proposed solution

I'd like for param matchers to return either a boolean (the current behavior) or a "canonical" param string which triggers a redirect. For example, if I want my blog slugs to only ever contain lowercase letters:

// params/isCanonicalSlug.ts

import type { ParamMatcher } from '@sveltejs/kit'

export const match: ParamMatcher = slug =>
    slug === slug.toLowerCase()
        ? true               // slug is valid
        : slug.toLowerCase() // slug is malformed, redirect to this slug instead

This way I can just define one route directory with a param matcher routes/blog/[slug=isCanonicalSlug] without extra files or custom load redirect logic.

Alternatives considered

Right now to achieve this, I have to implement a conditional redirect like this:

// routes/blog/[slug]/+layout.ts

import { redirect } from '@sveltejs/kit'
import type { LayoutLoad } from './$types'
 
export const load = (({ params }) => {
    if (params.slug !== params.slug.toLowerCase()) {
        throw redirect(308, params.slug.toLowerCase())
    }
}) satisfies LayoutLoad

Or for an existing pattern-matched route, add a "catch-all" route with a blank page that always redirects:

// params/isCanonicalSlug.ts

import type { ParamMatcher } from '@sveltejs/kit'

export const match: ParamMatcher = slug =>
    slug === slug.toLowerCase()
<!-- routes/blog/[slug=isCanonicalSlug]/+page.svelte -->

<script lang="ts">
    import { page } from '$app/stores'
</script>

{$page.params.slug}

The canonical blog post
<!-- routes/blog/[slug]/+page.svelte -->

<!-- (Not canon) -->
// routes/blog/[slug]/+layout.server.ts

import { redirect } from '@sveltejs/kit'
import type { LayoutServerLoad } from './$types'
 
export const load = (({ params }) => {
    throw redirect(308, params.slug.toLowerCase())
}) satisfies LayoutServerLoad

Importance

would make my life easier

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions