> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Real IP

> Real client IP extraction middleware for proxy environments.

## Overview

The `realip` middleware extracts the real client IP address from proxy headers. It's essential when running behind load balancers or reverse proxies.

## Installation

```go theme={null}
import "github.com/go-mizu/mizu/middlewares/realip"
```

## Quick Start

```go theme={null}
app := mizu.New()
app.Use(realip.New())
```

## Configuration

| Option           | Type       | Default   | Description             |
| ---------------- | ---------- | --------- | ----------------------- |
| `TrustedProxies` | `[]string` | -         | Trusted proxy IPs/CIDRs |
| `TrustedHeaders` | `[]string` | See below | Headers to check        |

### Default Headers (checked in order)

1. `X-Forwarded-For`
2. `X-Real-IP`
3. `CF-Connecting-IP` (Cloudflare)
4. `True-Client-IP`

## Examples

### Basic Usage

```go theme={null}
app.Use(realip.New())

app.Get("/", func(c *mizu.Ctx) error {
    ip := realip.Get(c)
    return c.Text(200, "Your IP: "+ip)
})
```

### Trusted Proxies

```go theme={null}
app.Use(realip.WithTrustedProxies(
    "10.0.0.0/8",
    "192.168.0.0/16",
))
```

### Custom Configuration

```go theme={null}
app.Use(realip.WithOptions(realip.Options{
    TrustedProxies: []string{"10.0.0.0/8"},
    TrustedHeaders: []string{
        "X-Real-IP",
        "X-Forwarded-For",
    },
}))
```

## API Reference

```go theme={null}
func New() mizu.Middleware
func WithTrustedProxies(proxies ...string) mizu.Middleware
func WithOptions(opts Options) mizu.Middleware
func FromContext(c *mizu.Ctx) string
func Get(c *mizu.Ctx) string  // Alias for FromContext
```

## Technical Details

### IP Extraction Process

The middleware follows a systematic approach to extract the real client IP:

1. **Remote IP Extraction**: Extracts the IP from `Request.RemoteAddr` using `net.SplitHostPort`
2. **Proxy Trust Verification**: Checks if the remote IP is in the trusted proxy list (CIDR notation supported)
3. **Header Processing**: If trusted, iterates through configured headers in priority order
4. **IP Parsing**: Extracts the first valid IP from comma-separated header values (for `X-Forwarded-For`)
5. **Fallback**: Uses `RemoteAddr` if no valid IP found in headers

### CIDR Network Parsing

The middleware automatically converts single IP addresses to CIDR notation:

* IPv4 addresses: `/32` suffix (e.g., `10.0.0.1` becomes `10.0.0.1/32`)
* IPv6 addresses: `/128` suffix (e.g., `::1` becomes `::1/128`)

### Context Storage

The real IP is stored in the request context using a private `contextKey{}` type, preventing key collisions with other middleware or application code.

### Header Priority

When multiple headers are set, the middleware checks them in the configured order and uses the first valid IP found. Default priority:

1. X-Forwarded-For (supports comma-separated lists)
2. X-Real-IP
3. CF-Connecting-IP (Cloudflare)
4. True-Client-IP

## Security

Only trust proxy headers when behind a trusted proxy. Without `TrustedProxies`, all requests are trusted.

## Testing

The middleware includes comprehensive test coverage for various scenarios:

| Test Case                               | Description                                        | Expected Behavior                                           |
| --------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------- |
| **Default Header Tests**                |                                                    |                                                             |
| `uses X-Forwarded-For`                  | Multiple IPs in X-Forwarded-For header             | Extracts first IP (203.0.113.195) from comma-separated list |
| `uses X-Real-IP`                        | Single IP in X-Real-IP header                      | Returns the IP from X-Real-IP (198.51.100.178)              |
| `uses CF-Connecting-IP`                 | Cloudflare connecting IP header                    | Returns the IP from CF-Connecting-IP (192.0.2.1)            |
| `falls back to RemoteAddr`              | No proxy headers present                           | Uses RemoteAddr (192.168.1.100)                             |
| **Trusted Proxy Tests**                 |                                                    |                                                             |
| `trusts headers from trusted proxy`     | Request from 10.0.0.1 with X-Forwarded-For         | Returns IP from header (203.0.113.195)                      |
| `ignores headers from untrusted source` | Request from 192.168.1.1 (not in trusted range)    | Ignores header, returns RemoteAddr (192.168.1.1)            |
| **Single IP Trust**                     |                                                    |                                                             |
| `WithTrustedProxies single IP`          | Trust specific IP (10.0.0.1)                       | Accepts headers from exact IP match                         |
| **Custom Headers**                      |                                                    |                                                             |
| `WithOptions custom headers`            | Configure X-Custom-IP as trusted header            | Extracts IP from custom header (5.6.7.8)                    |
| **API Compatibility**                   |                                                    |                                                             |
| `Get() alias test`                      | FromContext vs Get methods                         | Both return identical IP values                             |
| **Helper Function Tests**               |                                                    |                                                             |
| `extractFirstIP - single IP`            | Parse "203.0.113.195"                              | Returns 203.0.113.195                                       |
| `extractFirstIP - comma-separated`      | Parse "203.0.113.195, 70.41.3.18, 150.172.238.178" | Returns first IP (203.0.113.195)                            |
| `extractFirstIP - whitespace`           | Parse "  203.0.113.195  "                          | Trims and returns 203.0.113.195                             |
| `extractFirstIP - invalid`              | Parse "invalid"                                    | Returns empty string                                        |
| `extractFirstIP - empty`                | Parse ""                                           | Returns empty string                                        |
| `extractFirstIP - IPv6`                 | Parse "2001:db8::1"                                | Returns IPv6 address                                        |
| `extractIP - with port`                 | Parse "192.168.1.1:8080"                           | Returns IP without port (192.168.1.1)                       |
| `extractIP - without port`              | Parse "192.168.1.1"                                | Returns IP as-is (192.168.1.1)                              |
| `extractIP - IPv6 with port`            | Parse "\[::1]:8080"                                | Returns IPv6 without port (::1)                             |
| `isTrusted - within CIDR`               | Check 10.0.0.1 in 10.0.0.0/8                       | Returns true                                                |
| `isTrusted - edge of CIDR`              | Check 10.255.255.255 in 10.0.0.0/8                 | Returns true                                                |
| `isTrusted - outside CIDR`              | Check 11.0.0.1 in 10.0.0.0/8                       | Returns false                                               |
| `isTrusted - multiple networks`         | Check 192.168.1.1 in \[10.0.0.0/8, 192.168.0.0/16] | Returns true (matches second network)                       |

## Related Middlewares

* [forwarded](/middlewares/forwarded) - Full forwarded header parsing
* [ipfilter](/middlewares/ipfilter) - IP filtering
