Skip to content

Commit

Permalink
#1462: add limiter docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Badgerati committed Feb 8, 2025
1 parent 7981385 commit 196597a
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 172 deletions.
2 changes: 1 addition & 1 deletion docs/Tutorials/Middleware/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Middleware in Pode allows you to observe and edit the request/response objects f

Middleware is supported in both a global scope, using [`Add-PodeMiddleware`](../../../Functions/Middleware/Add-PodeMiddleware), as well as at the Route level using the `-Middleware` parameter on [`Add-PodeRoute`](../../../Functions/Routes/Add-PodeRoute).

Pode itself has some inbuilt Middleware, which is overridable, so you can use your own custom middleware. For example, Pode has inbuilt Middleware for rate limiting, but you can override this with [`Add-PodeMiddleware`](../../../Functions/Middleware/Add-PodeMiddleware) and the Name `__pode_mw_rate_limit__` (more on the [Access Rules](../Types/AccessRules) and [Rate Limiting](../Types/RateLimiting) page).
Pode itself has some inbuilt Middleware, which is overridable, so you can use your own custom middleware. For example, Pode has inbuilt Middleware for rate limiting, but you can override this with [`Add-PodeMiddleware`](../../../Functions/Middleware/Add-PodeMiddleware) and the Name `__pode_mw_rate_limit__` (more on the [Access Rules](../Types/Limiters/AccessRules) and [Rate Rules](../Types/Limiters/RateRules) page).

## Global Middleware

Expand Down
65 changes: 0 additions & 65 deletions docs/Tutorials/Middleware/Types/AccessRules.md

This file was deleted.

105 changes: 105 additions & 0 deletions docs/Tutorials/Middleware/Types/Limiters/AccessRules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Access Rules

Access rules in Pode are inbuilt Middleware that allow you to specify allow/deny rules for requests, built using [Limit Components](../Components). For example, you could deny certain IPs from accessing the server, and vice-versa by allowing them.

## Usage

To create access rules in Pode you use the [`Add-PodeLimitAccessRule`](../../../../../Functions/Limit/Add-PodeLimitAccessRule) function, together with a series of [Limit Components](../Components).

This page will give some quick examples of Access Rules, for more information on the components themselves go to the components page. However, in general you can use the components to build access rules to allow/deny IPs, subnets, access to specific Routes/Endpoints, etc.

!!! info
If a requests hits your server from an address that you've denied access, then a `403` response is returned and the connection immediately closed. For SMTP/TCP servers the connection is just closed with no response.

The following example will allow access for requests from localhost:

```powershell
Add-PodeLimitAccessRule -Name 'example' -Action Allow -Component @(
New-PodeLimitIPComponent -IP '127.0.0.1'
)
```

Whereas the following example will deny access for requests from a subnet:

```powershell
Add-PodeLimitAccessRule -Name 'example' -Action Deny -Component @(
New-PodeLimitIPComponent -IP '10.10.0.0/24'
)
```

You can also only allow localhost access to a `/downloads` route:

```powershell
Add-PodeLimitAccessRule -Name 'example' -Action Allow -Component @(
New-PodeLimitIPComponent -IP '127.0.0.1'
New-PodeLimitRouteComponent -Path '/downloads'
)
```

Or, deny all requests from a subnet, and send back a custom status code:

```powershell
Add-PodeLimitAccessRule -Name 'example' -Action Deny -StatusCode 401 -Component @(
New-PodeLimitIPComponent -IP '192.0.1.0/16'
)
```

As a last resort you can even deny all requests from any IP:

```powershell
Add-PodeLimitAccessRule -Name 'example' -Action Deny -Component @(
New-PodeLimitIPComponent
)
```

## Priority

By default, all access rules are created with a minimum priority - meaning the rules will be executed in the order they are created.

If you want to have more control over this, you can customise the priority via the `-Priority` parameter. The higher the value, the higher the priority. If two or more rules have the same priority, then they are run in creation order.

```powershell
Add-PodeLimitAccessRule -Name 'example' -Action Deny -Priority 100 -Component @(
New-PodeLimitIPComponent -IP '192.0.1.0/16'
)
```

## Functions

Other helper functions for access rules are:

* [`Update-PodeLimitAccessRule`](../../../../../Functions/Limit/Update-PodeLimitAccessRule)
* [`Remove-PodeLimitAccessRule`](../../../../../Functions/Limit/Remove-PodeLimitAccessRule)
* [`Test-PodeLimitAccessRule`](../../../../../Functions/Limit/Test-PodeLimitAccessRule)
* [`Get-PodeLimitAccessRule`](../../../../../Functions/Limit/Get-PodeLimitAccessRule)

## Overriding

Since access rules are an inbuilt Middleware in Pode, then when you create any rules the point at which the rules are checked on the request lifecycle is fixed (see [here](../../Overview/#order-of-running)).

This means you can override the inbuilt access rule logic with your own custom logic, using the [`Add-PodeMiddleware`](../../../../../Functions/Middleware/Add-PodeMiddleware) function. To override the access rule logic you can pass `__pode_mw_access__` to the `-Name` parameter of the [`Add-PodeMiddleware`](../../../../../Functions/Middleware/Add-PodeMiddleware) function.

The following example uses access rules, and defines Middleware that will override the inbuilt access logic:

```powershell
Start-PodeServer {
# attach to port 8080
Add-PodeEndpoint -Address * -Port 8080 -Protocol Http
# assign access rule to deny localhost
Add-PodeLimitAccessRule -Name 'example' -Action Deny -Component @(
New-PodeLimitIPComponent -IP @('127.0.0.1', '[::1]')
)
# create middleware to override the inbuilt access rule logic.
# this will ignore the 'deny' part, and just allow the request
Add-PodeMiddleware -Name '__pode_mw_access__' -ScriptBlock {
return $true
}
# basic route
Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
# logic
}
}
```
99 changes: 99 additions & 0 deletions docs/Tutorials/Middleware/Types/Limiters/Components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Components

When building limit rules - such as Access or Rate - you build them using various "components". The following inbuilt components currently exist:

* IP
* Route
* Endpoint
* Method
* Header

You can use these components on their own, or combine them to make more advanced limit rule configurations. For example, limit requests from a subnet to a specific group of Routes - say limiting requests to 10 per minute, to the Routes under `/api/*`:

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 10 -Duration 60000 -Component @(
New-PodeLimitIPComponent -Value '10.10.0.0/24' -Group
New-PodeLimitRouteComponent -Value '/api/*' -Group
)
```

## IP

An IP Component can be created via [`New-PodeLimitIPComponent`](../../../../../Functions/Limit/New-PodeLimitIPComponent). You can specify none, one, or more IP or subnet addresses - if none are supplied, then the component will match every IP.

```powershell
# match every IP - and treat them individually
New-PodeLimitIPComponent
# match every IP - but treat them as 1 entity
New-PodeLimitIPComponent -Group
# match specific IP address(es)
New-PodeLimitIPComponent -IP '10.0.0.92', '192.0.1.131'
# match all IPs in a subnet - and treat them individually
New-PodeLimitIPComponent -IP '10.0.1.0/16'
# match all IPs in a subnet - but treat them as 1 entity
New-PodeLimitIPComponent -IP '10.0.1.0/16' -Group
```

## Route

A Route Component can be created via [`New-PodeLimitRouteComponent`](../../../../../Functions/Limit/New-PodeLimitRouteComponent). You can specify none, one, or more Route paths - if none are supplied, then the component will match every Route path. You can also use wildcard/regex to match multiple Routes.

```powershell
# match every Route - and treat them individually
New-PodeLimitRouteComponent
# match every Route - but treat them as 1 entity
New-PodeLimitRouteComponent -Group
# match specific Route path(s)
New-PodeLimitRouteComponent -Path '/download', '/api/users'
# match all Routes via a wildcard - and treat them individually
New-PodeLimitRouteComponent -Path '/api/*'
# match all Routes via a wildcard - but treat them as 1 entity
New-PodeLimitRouteComponent -Path '/api/*' -Group
```

## Endpoint

An Endpoint Component can be created via [`New-PodeLimitEndpointComponent`](../../../../../Functions/Limit/New-PodeLimitEndpointComponent). You can specify none, one, or more Endpoint names - if none are supplied, then the component will match every Endpoint.

```powershell
# match every Endpoint - and treat them individually
New-PodeLimitEndpointComponent
# match specific Endpoint(s)
New-PodeLimitEndpointComponent -Name 'api', 'admin'
```

## Method

A Method Component can be created via [`New-PodeLimitMethodComponent`](../../../../../Functions/Limit/New-PodeLimitMethodComponent). You can specify none, one, or more HTTP methods - if none are supplied, then the component will match every method.

```powershell
# match every Method - and treat them individually
New-PodeLimitMethodComponent
# match specific Method(s)
New-PodeLimitMethodComponent -Method 'Get', 'Post'
```

## Header

A Header Component can be created via [`New-PodeLimitHeaderComponent`](../../../../../Functions/Limit/New-PodeLimitHeaderComponent). You can specify one or more Headers, and you can also specify specific values for the Headers to match on as well.

```powershell
# match a specific Header - and treat different values individually
New-PodeLimitHeaderComponent -Name 'X-API-KEY'
# match a specific Header - but ignore the value, and treat them as 1 entity
New-PodeLimitHeaderComponent -Name 'X-API-KEY' -Group
# match a specific Header, with a specific value
New-PodeLimitHeaderComponent -Name 'X-API-KEY' -Value '1c1aad92-194e-433a-bf0a-385434dcac13'
```
115 changes: 115 additions & 0 deletions docs/Tutorials/Middleware/Types/Limiters/RateRules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Rate Rules

Rate limiting in Pode is inbuilt Middleware, that allows you to specify a maximum number of requests within a defined duration, built using [Limit Components](../Components). For example, you could rate limit a specific IP to 10 requests per minute.

When rate limiting a subnet you can choose to either individually limit each IP address in a subnet, or you can group all IPs in a subnet together under a single limit.

## Usage

To create rate rules in Pode you use the [`Add-PodeLimitRateRule`](../../../../../Functions/Limit/Add-PodeLimitRateRule) function, together with a series of [Limit Components](../Components).

This page will give some quick examples of Rate Rules, for more information on the components themselves go to the components page. However, in general you can use the components to build rate rules to limit requests from IPs, subnets, to specific Routes/Endpoints, etc.

!!! info
If request hits the limit within the defined duration, then a `429` response is returned and the connection immediately closed. For SMTP/TCP servers the connection is just closed with no response.

The following example will limit requests from localhost to 5 requests per second:

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 5 -Duration 1000 -Component @(
New-PodeLimitIPComponent -Value '127.0.0.1'
)
```

Whereas the following example will rate limit requests from a subnet. By default each IP address within the subnet are limited to 5 requests per second:

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 5 -Duration 1000 -Component @(
New-PodeLimitIPComponent -Value '10.10.0.0/24'
)
```

To treat all IP addresses within by a subnet as one, using a shared limit, you can supply the `-Group` switch:

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 5 -Duration 1000 -Component @(
New-PodeLimitIPComponent -Value '10.10.0.0/24' -Group
)
```

Conversely, you could even limit requests from a subnet to a specific group of Routes - say limiting requests to 10 per minute, to the Routes under `/api/*`:

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 10 -Duration 60000 -Component @(
New-PodeLimitIPComponent -Value '10.10.0.0/24' -Group
New-PodeLimitRouteComponent -Value '/api/*' -Group
)
```

You can also limit requests to just a specific Route:

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 1 -Duration 60000 -Component @(
New-PodeLimitRouteComponent -Value '/download'
)
```

Or, limit requests by HTTP header. The following will limit each header value individually, or you can use `-Group` to treat the header as one value regardless of what is passed.

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 500 -Duration 60000 -Component @(
New-PodeLimitHeaderComponent -Name 'X-API-KEY'
)
```

## Priority

By default, all rate rules are created with a minimum priority - meaning the rules will be executed in the order they are created.

If you want to have more control over this, you can customise the priority via the `-Priority` parameter. The higher the value, the higher the priority. If two or more rules have the same priority, then they are run in creation order.

```powershell
Add-PodeLimitRateRule -Name 'example' -Limit 500 -Duration 60000 -Priority 100 -Component @(
New-PodeLimitHeaderComponent -Name 'X-API-KEY'
)
```

## Functions

Other helper functions for rate rules are:

* [`Update-PodeLimitRateRule`](../../../../../Functions/Limit/Update-PodeLimitRateRule)
* [`Remove-PodeLimitRateRule`](../../../../../Functions/Limit/Remove-PodeLimitRateRule)
* [`Test-PodeLimitRateRule`](../../../../../Functions/Limit/Test-PodeLimitRateRule)
* [`Get-PodeLimitRateRule`](../../../../../Functions/Limit/Get-PodeLimitRateRule)

## Overriding

Since rate limiting is an inbuilt Middleware, then when you setup rules the point at which the limit is checked on the request lifecycle is fixed (see [here](../../Overview/#order-of-running)).

This means you can override the inbuilt rate limiting logic, with your own custom logic, using the [`Add-PodeMiddleware`](../../../../../Functions/Middleware/Add-PodeMiddleware) function. To override the rate limiting logic you can pass `__pode_mw_rate_limit__` to the `-Name` parameter of the [`Add-PodeMiddleware`](../../../../../Functions/Middleware/Add-PodeMiddleware) function.

The following example uses rate limiting, and defines Middleware that will override the inbuilt limiting logic:

```powershell
Start-PodeServer {
# attach to port 8080
Add-PodeEndpoint -Address * -Port 8080 -Protocol Http
# assign limiting to localhost
Add-PodeLimitRateRule -Name 'example' -Limit 10 -Duration 2000 -Component @(
New-PodeLimitIPComponent -Value @('127.0.0.1', '[::1]')
)
# create middleware to override the inbuilt rate limiting logic.
# this will ignore the limiting part, and just allow the request
Add-PodeMiddleware -Name '__pode_mw_rate_limit__' -ScriptBlock {
return $true
}
# basic route
Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
# logic
}
}
```
Loading

0 comments on commit 196597a

Please sign in to comment.