Skip to content

Commit

Permalink
feat: improve case-sensitive slug handling
Browse files Browse the repository at this point in the history
Refactors URL slug case sensitivity implementation:
- Moves case conversion to creation time instead of lookup
- Updates middleware to handle case sensitivity more efficiently
- Adds configuration docs for case sensitivity and list query limits
- Simplifies nanoid implementation to always use lowercase

This change improves performance and consistency in URL handling while maintaining backwards compatibility with existing links.
  • Loading branch information
ccbikai committed Dec 25, 2024
1 parent af5724f commit 8d1bf6a
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 11 deletions.
8 changes: 8 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,11 @@ Default prompt:
```txt
You are a URL shortening assistant, please shorten the URL provided by the user into a SLUG. The SLUG information must come from the URL itself, do not make any assumptions. A SLUG is human-readable and should not exceed three words and can be validated using regular expressions {slugRegex} . Only the best one is returned, the format must be JSON reference {"slug": "example-slug"}
```

## `NUXT_CASE_SENSITIVE`

Set URL case sensitivity.

## `NUXT_LIST_QUERY_LIMIT`

Set the maximum query data volume for the Metric list.
4 changes: 4 additions & 0 deletions docs/faqs.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ However, you can disable this feature by setting the `NUXT_CASE_SENSITIVE` envir
### What happens when `NUXT_CASE_SENSITIVE` is `true`?

Newly generated links will be case-sensitive, treating `MyLink` and `mylink` as distinct. Randomly generated slugs will include both uppercase and lowercase characters, offering a larger pool of unique combinations (but not user-friendly that why we default to non-case-sensitive).

## 7. Why does the Metric list only show the top 500 data entries?

To improve query performance, we have limited the amount of data. If you need to query more data, you can adjust it through `NUXT_LIST_QUERY_LIMIT`.
7 changes: 1 addition & 6 deletions schemas/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ import { customAlphabet } from 'nanoid'
import { z } from 'zod'

const { slugRegex } = useAppConfig()
const { caseSensitive } = useRuntimeConfig()

const slugDefaultLength = +useRuntimeConfig().public.slugDefaultLength

export function nanoid(length: number = slugDefaultLength) {
return caseSensitive
? customAlphabet('23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ', length)
: customAlphabet('23456789abcdefghjkmnpqrstuvwxyz', length)
}
export const nanoid = (length: number = slugDefaultLength) => customAlphabet('23456789abcdefghjkmnpqrstuvwxyz', length)

export const LinkSchema = z.object({
id: z.string().trim().max(26).default(nanoid(10)),
Expand Down
6 changes: 6 additions & 0 deletions server/api/link/create.post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { LinkSchema } from '@/schemas/link'
export default eventHandler(async (event) => {
const link = await readValidatedBody(event, LinkSchema.parse)

const { caseSensitive } = useRuntimeConfig(event)

if (!caseSensitive) {
link.slug = link.slug.toLowerCase()
}

const { cloudflare } = event.context
const { KV } = cloudflare.env
const existingLink = await KV.get(`link:${link.slug}`)
Expand Down
10 changes: 5 additions & 5 deletions server/middleware/1.redirect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ export default eventHandler(async (event) => {
const getLink = async (key: string) =>
await KV.get(`link:${key}`, { type: 'json', cacheTtl: linkCacheTtl })

link = await getLink(slug)

// fallback to lowercase slug if caseSensitive is false and the slug is not found
const lowerCaseSlug = slug.toLowerCase()
link = await getLink(caseSensitive ? slug : lowerCaseSlug)

// fallback to original slug if caseSensitive is false and the slug is not found
if (!caseSensitive && !link && lowerCaseSlug !== slug) {
console.log('lowerCaseSlug fallback:', `slug:${slug} lowerCaseSlug:${lowerCaseSlug}`)
link = await getLink(lowerCaseSlug)
console.log('original slug fallback:', `slug:${slug} lowerCaseSlug:${lowerCaseSlug}`)
link = await getLink(slug)
}

if (link) {
Expand Down

0 comments on commit 8d1bf6a

Please sign in to comment.