Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Remove match option from rate limit config #109

Merged
merged 2 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
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
15 changes: 0 additions & 15 deletions src/content/docs/rate-limiting/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,6 @@ import Comments from "/src/components/Comments.astro";
Each Arcjet rate limit rule has its own configuration depending on the algorithm
used.

## Match

**Type:** `string` (optional)

**Algorithms:** `fixedWindow`, `slidingWindow`, `tokenBucket`.

The exact request path the rate limit applies to. If not specified and Arcjet is
running on a specific API route, it defaults to the path for that route. If not
specified and Arcjet is running from middleware, it applies to all routes.

Wildcards are not currently supported. This is on our roadmap, but in the
meantime see [this Next.js
example](/rate-limiting/reference/nextjs#wildcard-matching-paths) for using
middleware conditionals.

## Characteristics

**Type:** `Array<string>` (optional)
Expand Down
3 changes: 0 additions & 3 deletions src/content/docs/rate-limiting/reference/bun.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type FixedWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
window: string; // time window the rate limit applies to
max: number; // maximum number of requests allowed in the time window
Expand All @@ -72,7 +71,6 @@ details about how the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type SlidingWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
interval: number; // the time interval in seconds for the rate limit
max: number; // maximum number of requests allowed over the time interval
Expand All @@ -98,7 +96,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type TokenBucketRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
refillRate: number; // number of tokens to add to the bucket at each interval
interval: number; // the interval in seconds to add tokens to the bucket
Expand Down
26 changes: 8 additions & 18 deletions src/content/docs/rate-limiting/reference/nextjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import ByUserIdAppJS from "/src/snippets/rate-limiting/reference/nextjs/ByUserId
import ByUserIdPagesJS from "/src/snippets/rate-limiting/reference/nextjs/ByUserIdPages.js?raw";
import SingleRateLimit from "/src/snippets/rate-limiting/reference/nextjs/SingleRateLimit.ts?raw";
import DryRun from "/src/snippets/rate-limiting/reference/nextjs/DryRun.ts?raw";
import MiddlewareSingleRoute from "/src/snippets/rate-limiting/reference/nextjs/MiddlewareSingleRoute.ts?raw";
import MiddlewareMatchingPaths from "/src/snippets/rate-limiting/reference/nextjs/MiddlewareMatchingPaths.ts?raw";
import MiddlewareAllRoutes from "/src/snippets/rate-limiting/reference/nextjs/MiddlewareAllRoutes.ts?raw";
import MiddlewareMatcher from "/src/snippets/rate-limiting/reference/nextjs/MiddlewareMatcher.ts?raw";
Expand Down Expand Up @@ -81,7 +80,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type FixedWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
window: string; // time window the rate limit applies to
max: number; // maximum number of requests allowed in the time window
Expand All @@ -105,7 +103,6 @@ details about how the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type SlidingWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
interval: number; // the time interval in seconds for the rate limit
max: number; // maximum number of requests allowed over the time interval
Expand All @@ -131,7 +128,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type TokenBucketRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
refillRate: number; // number of tokens to add to the bucket at each interval
interval: number; // the interval in seconds to add tokens to the bucket
Expand Down Expand Up @@ -248,14 +244,16 @@ Rate limit rules can be configured in two ways:

### Per route

If you define your rate limit within an API route and do not specify a value for
`match`, Arcjet assumes that the limit applies only to that route. If you define
your rate limit in middleware, you should specify a path for `match` otherwise
the rate limit will apply to all routes.
If you define your rate limit within an API route Arcjet assumes that the limit
applies only to that route. If you define your rate limit in middleware, you
should either use the Next.js `matcher` config to choose which paths to execute
the middleware for, or use `request.nextUrl.pathname.startsWith`.

#### Rate limit only on `/api/hello`
#### Rate limit only on `/api/*`

<Code code={MiddlewareSingleRoute} title="/middleware.ts" lang="ts" />
You can use conditionals in your Next.js middleware to match multiple paths.

<Code code={MiddlewareMatchingPaths} title="/middleware.ts" lang="ts" />

#### Rate limit on all routes

Expand Down Expand Up @@ -605,14 +603,6 @@ narrowly identify each client, such as an API key as shown here.

<Code code={ByAPIKeyHeader} lang="ts" />

### Wildcard matching paths

The Arcjet rate limit `match` configuration does not currently support
wildcards. This is on our roadmap, but in the meantime you can use conditionals
in your Next.js middleware instead.

<Code code={MiddlewareMatchingPaths} title="/middleware.ts" lang="ts" />

### Global rate limit

Using Next.js middleware allows you to set a rate limit that applies to every
Expand Down
3 changes: 0 additions & 3 deletions src/content/docs/rate-limiting/reference/nodejs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type FixedWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
window: string; // time window the rate limit applies to
max: number; // maximum number of requests allowed in the time window
Expand All @@ -73,7 +72,6 @@ details about how the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type SlidingWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
interval: number; // the time interval in seconds for the rate limit
max: number; // maximum number of requests allowed over the time interval
Expand All @@ -99,7 +97,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type TokenBucketRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
refillRate: number; // number of tokens to add to the bucket at each interval
interval: number; // the interval in seconds to add tokens to the bucket
Expand Down
37 changes: 7 additions & 30 deletions src/content/docs/rate-limiting/reference/sveltekit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import ByUserIdTS from "/src/snippets/rate-limiting/reference/sveltekit/ByUserId
import ByUserIdJS from "/src/snippets/rate-limiting/reference/sveltekit/ByUserId.js?raw";
import SingleRateLimit from "/src/snippets/rate-limiting/reference/sveltekit/SingleRateLimit.ts?raw";
import DryRun from "/src/snippets/rate-limiting/reference/sveltekit/DryRun.ts?raw";
import HookSingleRoute from "/src/snippets/rate-limiting/reference/sveltekit/HookSingleRoute.ts?raw";
import HookMatchingPaths from "/src/snippets/rate-limiting/reference/sveltekit/HookMatchingPaths.ts?raw";
import HookAllRoutes from "/src/snippets/rate-limiting/reference/sveltekit/HookAllRoutes.ts?raw";
import HookMatcher from "/src/snippets/rate-limiting/reference/sveltekit/HookMatcher.ts?raw";
Expand Down Expand Up @@ -57,7 +56,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type ConfigFixedWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
window: string; // time window the rate limit applies to
max: number; // maximum number of requests allowed in the time window
Expand All @@ -81,7 +79,6 @@ details about how the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type ConfigSlidingWindowRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
interval: number; // the time interval in seconds for the rate limit
max: number; // maximum number of requests allowed over the time interval
Expand All @@ -107,7 +104,6 @@ the algorithm works.
// See https://docs.arcjet.com/rate-limiting/configuration
type TokenBucketRateLimitOptions = {
mode?: "LIVE" | "DRY_RUN"; // "LIVE" will block requests. "DRY_RUN" will log only
match?: string; // request path the rate limit applies to
characteristics?: string[]; // how the client is identified. Defaults to the global characteristics if unset
refillRate: number; // number of tokens to add to the bucket at each interval
interval: number; // the interval in seconds to add tokens to the bucket
Expand Down Expand Up @@ -201,28 +197,22 @@ Rate limit rules can be configured in two ways:

### Per route

If you define your rate limit within a route and do not specify a value for
`match`, Arcjet assumes that the limit applies only to that route. If you define
your rate limit in hooks, you should specify a path for `match` otherwise
the rate limit will apply to all routes.
If you define your rate limit within an API route Arcjet assumes that the limit
applies only to that route. If you define your rate limit in hooks, you should
use `event.url.pathname.startsWith`.

#### Rate limit only on `/api`
#### Rate limit only on `/api/*`

<Code
code={HookSingleRoute}
code={HookMatchingPaths}
title="/src/hooks.server.ts"
lang="ts"
mark={[{ range: "10-11" }]}
mark={[{ range: "23-24" }]}
/>

#### Rate limit on all routes

<Code
code={HookAllRoutes}
title="/src/hooks.server.ts"
lang="ts"
mark={[{ range: "10-11" }]}
/>
<Code code={HookAllRoutes} title="/src/hooks.server.ts" lang="ts" />

### Avoiding double protection with hooks

Expand Down Expand Up @@ -523,19 +513,6 @@ narrowly identify each client, such as an API key as shown here.

<Code code={ByAPIKeyHeader} lang="ts" mark={[{ range: "9" }]} />

### Wildcard matching paths

The Arcjet rate limit `match` configuration does not currently support
wildcards. This is on our roadmap, but in the meantime you can use conditionals
in your SvelteKit hook instead.

<Code
code={HookMatchingPaths}
title="/src/hooks.server.ts"
lang="ts"
mark={[{ range: "23-24" }]}
/>

### Global rate limit

Using SvelteKit hooks allows you to set a rate limit that applies to every
Expand Down
2 changes: 0 additions & 2 deletions src/content/docs/reference/bun.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,12 @@ const aj = arcjet({
// This rule is live
{
mode: "LIVE",
match: "/api/arcjet",
window: "1h",
max: 60,
},
// This rule is in dry run mode, so will log but not block
{
mode: "DRY_RUN",
match: "/api/arcjet",
characteristics: ['http.request.headers["x-api-key"]'],
window: "1h",
// max could also be a dynamic value applied after looking up a limit
Expand Down
2 changes: 0 additions & 2 deletions src/content/docs/reference/nextjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,12 @@ const aj = arcjet({
// This rule is live
{
mode: "LIVE",
match: "/api/hello",
window: "1h",
max: 60,
},
// This rule is in dry run mode, so will log but not block
{
mode: "DRY_RUN",
match: "/api/hello",
characteristics: ['http.request.headers["x-api-key"]'],
window: "1h",
// max could also be a dynamic value applied after looking up a limit
Expand Down
2 changes: 0 additions & 2 deletions src/content/docs/reference/sveltekit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,12 @@ const aj = arcjet({
// This rule is live
{
mode: "LIVE",
match: "/api/arcjet",
window: "1h",
max: 60,
},
// This rule is in dry run mode, so will log but not block
{
mode: "DRY_RUN",
match: "/api/arcjet",
characteristics: ['http.request.headers["x-api-key"]'],
window: "1h",
// max could also be a dynamic value applied after looking up a limit
Expand Down
2 changes: 0 additions & 2 deletions src/snippets/rate-limiting/reference/bun/DryRun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ const aj = arcjet({
// This rule is live
fixedWindow({
mode: "LIVE",
match: "/api/hello",
window: "1h",
max: 60,
}),
// This rule is in dry run mode, so will log but not block
fixedWindow({
mode: "DRY_RUN",
match: "/api/hello",
// Setting the characteristics in the rule itself overrides the global
// setting
characteristics: ['http.request.headers["x-api-key"]'],
Expand Down
1 change: 0 additions & 1 deletion src/snippets/rate-limiting/reference/bun/FixedWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const aj = arcjet({
rules: [
fixedWindow({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
match: "/api/hello", // match all requests to /api/hello
window: "60s", // 60 second fixed window
max: 100, // allow a maximum of 100 requests
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const aj = arcjet({
rules: [
slidingWindow({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
match: "/api/hello", // match all requests to /api/hello
interval: 60, // 60 second sliding window
max: 100, // allow a maximum of 100 requests
}),
Expand Down
1 change: 0 additions & 1 deletion src/snippets/rate-limiting/reference/bun/SlidingWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const aj = arcjet({
rules: [
slidingWindow({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
match: "/api/hello", // match all requests to /api/hello
interval: 60, // 60 second sliding window
max: 100, // allow a maximum of 100 requests
}),
Expand Down
1 change: 0 additions & 1 deletion src/snippets/rate-limiting/reference/bun/TokenBucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const aj = arcjet({
rules: [
tokenBucket({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
match: "/api/hello", // match all requests to /api/hello
refillRate: 10, // refill 10 tokens per interval
interval: 60, // 60 second interval
capacity: 100, // bucket maximum capacity of 100 tokens
Expand Down
2 changes: 0 additions & 2 deletions src/snippets/rate-limiting/reference/nextjs/DryRun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ const aj = arcjet({
// This rule is live
fixedWindow({
mode: "LIVE",
match: "/api/hello",
window: "1h",
max: 60,
}),
// This rule is in dry run mode, so will log but not block
fixedWindow({
mode: "DRY_RUN",
match: "/api/hello",
characteristics: ['http.request.headers["x-api-key"]'],
window: "1h",
// max could also be a dynamic value applied after looking up a limit
Expand Down
1 change: 0 additions & 1 deletion src/snippets/rate-limiting/reference/nextjs/FixedWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const aj = arcjet({
rules: [
fixedWindow({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
match: "/api/hello", // match all requests to /api/hello
window: "60s", // 60 second fixed window
max: 100, // allow a maximum of 100 requests
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const aj = arcjet({
rules: [
fixedWindow({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
match: "/api/hello", // match all requests to /api/hello
window: "60s", // 60 second fixed window
max: 100, // allow a maximum of 100 requests
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const aj = arcjet({
rules: [
fixedWindow({
mode: "LIVE", // will block requests. Use "DRY_RUN" to log only
match: "/api/hello", // match all requests to /api/hello
window: "60s", // 60 second fixed window
max: 100, // allow a maximum of 100 requests
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const aj = arcjet({
rules: [
fixedWindow({
mode: "LIVE",
// no match means it runs on every route
//match: "/api/hello",
window: "1h",
max: 60,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const aj = arcjet({
rules: [
fixedWindow({
mode: "LIVE",
// no match means it runs on every route
//match: "/api/hello",
window: "1h",
max: 60,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const aj = arcjet({
rules: [
fixedWindow({
mode: "LIVE",
// no match means it runs on every route
//match: "/api/hello",
window: "1h",
max: 60,
}),
Expand Down
Loading