anky2002 commited on
Commit
d9d3c8f
·
verified ·
1 Parent(s): d70eff5

fix: search rate limit now properly applies stricter limits for semantic search

Browse files
Files changed (1) hide show
  1. src/app/api/search/route.ts +17 -6
src/app/api/search/route.ts CHANGED
@@ -24,16 +24,28 @@ export async function GET(request: NextRequest) {
24
  )
25
  }
26
 
27
- // Rate limit — semantic search is expensive, stricter limit
28
  const authUser = await getAuthUser()
29
  const identifier = getClientIdentifier(request, authUser?.id ?? undefined)
30
- const preset = semantic ? `search-semantic:${identifier}` : `search:${identifier}`
31
- const maxReqs = semantic ? 10 : 60
32
- const rateLimit = await checkRateLimit(preset, !!authUser)
33
  if (!rateLimit.success) {
34
  return NextResponse.json({ error: rateLimit.error }, { status: 429 })
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  // Build base query
38
  const whereClause: Record<string, unknown> = {
39
  visibility: "public",
@@ -81,7 +93,7 @@ Return ONLY a comma-separated list of terms, nothing else.`,
81
  }
82
  }
83
 
84
- // Build OR clause for search — exclude template field (too expensive for ILIKE)
85
  const orClause = searchTerms.flatMap(term => [
86
  { title: { contains: term, mode: "insensitive" as const } },
87
  { description: { contains: term, mode: "insensitive" as const } },
@@ -175,7 +187,6 @@ Return ONLY a comma-separated list of terms, nothing else.`,
175
  hasMore: offset + prompts.length < total,
176
  }, {
177
  headers: {
178
- // Short cache for search results
179
  'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
180
  },
181
  })
 
24
  )
25
  }
26
 
27
+ // Rate limit — semantic search is expensive, use a stricter key prefix
28
  const authUser = await getAuthUser()
29
  const identifier = getClientIdentifier(request, authUser?.id ?? undefined)
30
+ const rateLimitKey = semantic ? `search-semantic:${identifier}` : `search:${identifier}`
31
+ const rateLimit = await checkRateLimit(rateLimitKey, !!authUser, false)
32
+
33
  if (!rateLimit.success) {
34
  return NextResponse.json({ error: rateLimit.error }, { status: 429 })
35
  }
36
 
37
+ // For semantic search, apply a secondary per-minute burst limit
38
+ if (semantic) {
39
+ const burstKey = `search-semantic-burst:${identifier}`
40
+ const burstLimit = await checkRateLimit(burstKey, !!authUser, false)
41
+ if (!burstLimit.success) {
42
+ return NextResponse.json(
43
+ { error: "Semantic search rate limit exceeded. Please wait a moment." },
44
+ { status: 429 }
45
+ )
46
+ }
47
+ }
48
+
49
  // Build base query
50
  const whereClause: Record<string, unknown> = {
51
  visibility: "public",
 
93
  }
94
  }
95
 
96
+ // Build OR clause for search
97
  const orClause = searchTerms.flatMap(term => [
98
  { title: { contains: term, mode: "insensitive" as const } },
99
  { description: { contains: term, mode: "insensitive" as const } },
 
187
  hasMore: offset + prompts.length < total,
188
  }, {
189
  headers: {
 
190
  'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
191
  },
192
  })