fastapi-ipware


Namefastapi-ipware JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryFastAPI/Starlette-native wrapper for python-ipware to get client IP addresses
upload_time2025-11-01 18:34:00
maintainerNone
docs_urlNone
authorMichael Bianco
requires_python>=3.10
licenseNone
keywords fastapi starlette ipware ip-address client-ip proxy x-forwarded-for
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # fastapi-ipware

A FastAPI/Starlette-native wrapper for [python-ipware](https://github.com/un33k/python-ipware) that eliminates the need for WSGI-style header conversion.

## Features

- **Zero conversion overhead** - Headers converted once at initialization, not on every request
- **FastAPI-native API** - Works directly with FastAPI/Starlette `Request` objects
- **Customizable precedence** - Easy to configure header priority for your infrastructure
- **Proxy validation** - Supports trusted proxy lists and proxy count validation
- **Thin wrapper** - Leverages all the battle-tested logic from python-ipware

## Installation

```bash
pip install fastapi-ipware
```

Or with uv:

```bash
uv add fastapi-ipware
```

## Quick Start

```python
from fastapi import FastAPI, Request
from fastapi_ipware import FastAPIIpWare

app = FastAPI()
ipware = FastAPIIpWare()

@app.get("/")
async def get_ip(request: Request):
    ip, trusted = ipware.get_client_ip_from_request(request)
    
    if ip:
        return {
            "ip": str(ip),
            "trusted": trusted,
            "is_public": ip.is_global,
            "is_private": ip.is_private,
        }
    
    return {"error": "Could not determine IP"}
```

## Usage

### Basic Usage

```python
from fastapi_ipware import FastAPIIpWare

# Use default configuration (optimized for FastAPI/cloud deployments)
ipware = FastAPIIpWare()

ip, trusted = ipware.get_client_ip_from_request(request)
```

### Custom Header Precedence

Customize which headers are checked and in what order:

```python
# Prioritize Cloudflare headers
ipware = FastAPIIpWare(
    precedence=(
        "CF-Connecting-IP",
        "X-Forwarded-For",
        "X-Real-IP",
    )
)

# NGINX configuration
ipware = FastAPIIpWare(
    precedence=(
        "X-Real-IP",
        "X-Forwarded-For",
    )
)
```

### Proxy Count Validation

Validate that requests pass through the expected number of proxies:

```python
# Expect exactly 1 proxy (e.g., AWS ALB)
ipware = FastAPIIpWare(proxy_count=1)

# In strict mode, must be exactly 1 proxy
ip, trusted = ipware.get_client_ip_from_request(request, strict=True)

# In non-strict mode, allow 1 or more proxies
ip, trusted = ipware.get_client_ip_from_request(request, strict=False)
```

### Trusted Proxy List

Validate that requests pass through specific trusted proxies:

```python
# Trust specific proxy IP prefixes
ipware = FastAPIIpWare(
    proxy_list=["10.0.", "10.1."]  # AWS internal IPs
)

ip, trusted = ipware.get_client_ip_from_request(request)

# trusted=True only if request came through specified proxies
```

### Combined Validation

Use both proxy count and trusted proxy list:

```python
# Expect 1 proxy from a specific IP range
ipware = FastAPIIpWare(
    proxy_count=1,
    proxy_list=["10.0."]
)
```

## Real-World Examples

### AWS Application Load Balancer

```python
ipware = FastAPIIpWare(
    proxy_count=1,
    proxy_list=["10.0."]  # Your VPC CIDR
)
```

### Cloudflare

```python
ipware = FastAPIIpWare(
    precedence=("CF-Connecting-IP",)
)
```

### Multiple Proxies (CDN + Load Balancer)

```python
ipware = FastAPIIpWare(
    proxy_count=2,
    proxy_list=["10.1.", "10.2."]  # CDN and LB IPs
)
```

### NGINX Reverse Proxy

```python
ipware = FastAPIIpWare(
    precedence=("X-Real-IP", "X-Forwarded-For"),
    proxy_count=1
)
```

## IP Address Types

The returned IP address object has useful properties:

```python
ip, _ = ipware.get_client_ip_from_request(request)

if ip:
    print(f"Is public: {ip.is_global}")
    print(f"Is private: {ip.is_private}")
    print(f"Is loopback: {ip.is_loopback}")
    print(f"Is multicast: {ip.is_multicast}")
```

python-ipware automatically prefers:
1. Public (global) IPs first
2. Private IPs second
3. Loopback IPs last

## Default Header Precedence

The default precedence order is optimized for modern cloud deployments. See the [default precedence configuration](https://github.com/iloveitaly/fastapi-ipware/blob/main/fastapi_ipware/__init__.py#L48-L58) in the source code.

## Why fastapi-ipware?

`python-ipware` expects WSGI-style headers (`HTTP_X_FORWARDED_FOR`), but FastAPI uses natural header names (`X-Forwarded-For`). This wrapper handles the conversion automatically so you don't have to.

## Contributing

Contributions welcome! This is a thin wrapper around python-ipware, so most IP detection logic lives there.

## License

[MIT License](LICENSE.md)

## Credits

Built on top of [python-ipware](https://github.com/un33k/python-ipware) by un33k.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fastapi-ipware",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "fastapi, starlette, ipware, ip-address, client-ip, proxy, x-forwarded-for",
    "author": "Michael Bianco",
    "author_email": "Michael Bianco <mike@mikebian.co>",
    "download_url": "https://files.pythonhosted.org/packages/24/4e/4bf916385541ec40c150ba920098f467d6187f9bf7f7e15460a0488b5447/fastapi_ipware-0.1.1.tar.gz",
    "platform": null,
    "description": "# fastapi-ipware\n\nA FastAPI/Starlette-native wrapper for [python-ipware](https://github.com/un33k/python-ipware) that eliminates the need for WSGI-style header conversion.\n\n## Features\n\n- **Zero conversion overhead** - Headers converted once at initialization, not on every request\n- **FastAPI-native API** - Works directly with FastAPI/Starlette `Request` objects\n- **Customizable precedence** - Easy to configure header priority for your infrastructure\n- **Proxy validation** - Supports trusted proxy lists and proxy count validation\n- **Thin wrapper** - Leverages all the battle-tested logic from python-ipware\n\n## Installation\n\n```bash\npip install fastapi-ipware\n```\n\nOr with uv:\n\n```bash\nuv add fastapi-ipware\n```\n\n## Quick Start\n\n```python\nfrom fastapi import FastAPI, Request\nfrom fastapi_ipware import FastAPIIpWare\n\napp = FastAPI()\nipware = FastAPIIpWare()\n\n@app.get(\"/\")\nasync def get_ip(request: Request):\n    ip, trusted = ipware.get_client_ip_from_request(request)\n    \n    if ip:\n        return {\n            \"ip\": str(ip),\n            \"trusted\": trusted,\n            \"is_public\": ip.is_global,\n            \"is_private\": ip.is_private,\n        }\n    \n    return {\"error\": \"Could not determine IP\"}\n```\n\n## Usage\n\n### Basic Usage\n\n```python\nfrom fastapi_ipware import FastAPIIpWare\n\n# Use default configuration (optimized for FastAPI/cloud deployments)\nipware = FastAPIIpWare()\n\nip, trusted = ipware.get_client_ip_from_request(request)\n```\n\n### Custom Header Precedence\n\nCustomize which headers are checked and in what order:\n\n```python\n# Prioritize Cloudflare headers\nipware = FastAPIIpWare(\n    precedence=(\n        \"CF-Connecting-IP\",\n        \"X-Forwarded-For\",\n        \"X-Real-IP\",\n    )\n)\n\n# NGINX configuration\nipware = FastAPIIpWare(\n    precedence=(\n        \"X-Real-IP\",\n        \"X-Forwarded-For\",\n    )\n)\n```\n\n### Proxy Count Validation\n\nValidate that requests pass through the expected number of proxies:\n\n```python\n# Expect exactly 1 proxy (e.g., AWS ALB)\nipware = FastAPIIpWare(proxy_count=1)\n\n# In strict mode, must be exactly 1 proxy\nip, trusted = ipware.get_client_ip_from_request(request, strict=True)\n\n# In non-strict mode, allow 1 or more proxies\nip, trusted = ipware.get_client_ip_from_request(request, strict=False)\n```\n\n### Trusted Proxy List\n\nValidate that requests pass through specific trusted proxies:\n\n```python\n# Trust specific proxy IP prefixes\nipware = FastAPIIpWare(\n    proxy_list=[\"10.0.\", \"10.1.\"]  # AWS internal IPs\n)\n\nip, trusted = ipware.get_client_ip_from_request(request)\n\n# trusted=True only if request came through specified proxies\n```\n\n### Combined Validation\n\nUse both proxy count and trusted proxy list:\n\n```python\n# Expect 1 proxy from a specific IP range\nipware = FastAPIIpWare(\n    proxy_count=1,\n    proxy_list=[\"10.0.\"]\n)\n```\n\n## Real-World Examples\n\n### AWS Application Load Balancer\n\n```python\nipware = FastAPIIpWare(\n    proxy_count=1,\n    proxy_list=[\"10.0.\"]  # Your VPC CIDR\n)\n```\n\n### Cloudflare\n\n```python\nipware = FastAPIIpWare(\n    precedence=(\"CF-Connecting-IP\",)\n)\n```\n\n### Multiple Proxies (CDN + Load Balancer)\n\n```python\nipware = FastAPIIpWare(\n    proxy_count=2,\n    proxy_list=[\"10.1.\", \"10.2.\"]  # CDN and LB IPs\n)\n```\n\n### NGINX Reverse Proxy\n\n```python\nipware = FastAPIIpWare(\n    precedence=(\"X-Real-IP\", \"X-Forwarded-For\"),\n    proxy_count=1\n)\n```\n\n## IP Address Types\n\nThe returned IP address object has useful properties:\n\n```python\nip, _ = ipware.get_client_ip_from_request(request)\n\nif ip:\n    print(f\"Is public: {ip.is_global}\")\n    print(f\"Is private: {ip.is_private}\")\n    print(f\"Is loopback: {ip.is_loopback}\")\n    print(f\"Is multicast: {ip.is_multicast}\")\n```\n\npython-ipware automatically prefers:\n1. Public (global) IPs first\n2. Private IPs second\n3. Loopback IPs last\n\n## Default Header Precedence\n\nThe default precedence order is optimized for modern cloud deployments. See the [default precedence configuration](https://github.com/iloveitaly/fastapi-ipware/blob/main/fastapi_ipware/__init__.py#L48-L58) in the source code.\n\n## Why fastapi-ipware?\n\n`python-ipware` expects WSGI-style headers (`HTTP_X_FORWARDED_FOR`), but FastAPI uses natural header names (`X-Forwarded-For`). This wrapper handles the conversion automatically so you don't have to.\n\n## Contributing\n\nContributions welcome! This is a thin wrapper around python-ipware, so most IP detection logic lives there.\n\n## License\n\n[MIT License](LICENSE.md)\n\n## Credits\n\nBuilt on top of [python-ipware](https://github.com/un33k/python-ipware) by un33k.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "FastAPI/Starlette-native wrapper for python-ipware to get client IP addresses",
    "version": "0.1.1",
    "project_urls": {
        "Repository": "https://github.com/iloveitaly/fastapi-ipware"
    },
    "split_keywords": [
        "fastapi",
        " starlette",
        " ipware",
        " ip-address",
        " client-ip",
        " proxy",
        " x-forwarded-for"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e657a5bb5d4407a11467b5cd5dd46803133a5f7e213ae25d5939827f426e45c3",
                "md5": "8fd94f5b3b5fe6189bd201db5d2b06c6",
                "sha256": "eb47c9dfd3b7962aac81b1fb603c4f5cda5450c905b47773d2ee625b1ecb2277"
            },
            "downloads": -1,
            "filename": "fastapi_ipware-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8fd94f5b3b5fe6189bd201db5d2b06c6",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 4877,
            "upload_time": "2025-11-01T18:33:59",
            "upload_time_iso_8601": "2025-11-01T18:33:59.714080Z",
            "url": "https://files.pythonhosted.org/packages/e6/57/a5bb5d4407a11467b5cd5dd46803133a5f7e213ae25d5939827f426e45c3/fastapi_ipware-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "244e4bf916385541ec40c150ba920098f467d6187f9bf7f7e15460a0488b5447",
                "md5": "594afd7a6fca2d57f07c85536d4d61af",
                "sha256": "2e2e638e57b8e0f3c08cbea32fca96713302cdcec380b6ea9eb216eae949eb3f"
            },
            "downloads": -1,
            "filename": "fastapi_ipware-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "594afd7a6fca2d57f07c85536d4d61af",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 4054,
            "upload_time": "2025-11-01T18:34:00",
            "upload_time_iso_8601": "2025-11-01T18:34:00.856206Z",
            "url": "https://files.pythonhosted.org/packages/24/4e/4bf916385541ec40c150ba920098f467d6187f9bf7f7e15460a0488b5447/fastapi_ipware-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-11-01 18:34:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "iloveitaly",
    "github_project": "fastapi-ipware",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "fastapi-ipware"
}
        
Elapsed time: 1.55293s