fastapi-ipware 0.1.1__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fastapi-ipware
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: FastAPI/Starlette-native wrapper for python-ipware to get client IP addresses
5
5
  Keywords: fastapi,starlette,ipware,ip-address,client-ip,proxy,x-forwarded-for
6
6
  Author: Michael Bianco
@@ -15,28 +15,28 @@ Description-Content-Type: text/markdown
15
15
 
16
16
  A FastAPI/Starlette-native wrapper for [python-ipware](https://github.com/un33k/python-ipware) that eliminates the need for WSGI-style header conversion.
17
17
 
18
+ `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.
19
+
20
+ Also, 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. This is different from the
21
+ default ordering ipware which deprioritizes platform-specific headers, which is often the wrong ordering if you are using something like CloudFlare.
22
+
18
23
  ## Features
19
24
 
20
25
  - **Zero conversion overhead** - Headers converted once at initialization, not on every request
21
26
  - **FastAPI-native API** - Works directly with FastAPI/Starlette `Request` objects
22
27
  - **Customizable precedence** - Easy to configure header priority for your infrastructure
23
28
  - **Proxy validation** - Supports trusted proxy lists and proxy count validation
24
- - **Thin wrapper** - Leverages all the battle-tested logic from python-ipware
25
29
 
26
30
  ## Installation
27
31
 
28
- ```bash
29
- pip install fastapi-ipware
30
- ```
31
-
32
- Or with uv:
33
-
34
32
  ```bash
35
33
  uv add fastapi-ipware
36
34
  ```
37
35
 
38
36
  ## Quick Start
39
37
 
38
+ [Take a look at this example usage.](https://github.com/iloveitaly/structlog-config/blob/1e32f7afd206485b1356b322596cc19cb0bef8ba/structlog_config/fastapi_access_logger.py#L57-L72)
39
+
40
40
  ```python
41
41
  from fastapi import FastAPI, Request
42
42
  from fastapi_ipware import FastAPIIpWare
@@ -137,43 +137,6 @@ ipware = FastAPIIpWare(
137
137
  )
138
138
  ```
139
139
 
140
- ## Real-World Examples
141
-
142
- ### AWS Application Load Balancer
143
-
144
- ```python
145
- ipware = FastAPIIpWare(
146
- proxy_count=1,
147
- proxy_list=["10.0."] # Your VPC CIDR
148
- )
149
- ```
150
-
151
- ### Cloudflare
152
-
153
- ```python
154
- ipware = FastAPIIpWare(
155
- precedence=("CF-Connecting-IP",)
156
- )
157
- ```
158
-
159
- ### Multiple Proxies (CDN + Load Balancer)
160
-
161
- ```python
162
- ipware = FastAPIIpWare(
163
- proxy_count=2,
164
- proxy_list=["10.1.", "10.2."] # CDN and LB IPs
165
- )
166
- ```
167
-
168
- ### NGINX Reverse Proxy
169
-
170
- ```python
171
- ipware = FastAPIIpWare(
172
- precedence=("X-Real-IP", "X-Forwarded-For"),
173
- proxy_count=1
174
- )
175
- ```
176
-
177
140
  ## IP Address Types
178
141
 
179
142
  The returned IP address object has useful properties:
@@ -189,26 +152,16 @@ if ip:
189
152
  ```
190
153
 
191
154
  python-ipware automatically prefers:
155
+
192
156
  1. Public (global) IPs first
193
157
  2. Private IPs second
194
158
  3. Loopback IPs last
195
159
 
196
- ## Default Header Precedence
197
-
198
- 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.
199
-
200
- ## Why fastapi-ipware?
201
-
202
- `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.
203
-
204
- ## Contributing
205
-
206
- Contributions welcome! This is a thin wrapper around python-ipware, so most IP detection logic lives there.
207
-
208
160
  ## License
209
161
 
210
162
  [MIT License](LICENSE.md)
211
163
 
212
164
  ## Credits
213
165
 
214
- Built on top of [python-ipware](https://github.com/un33k/python-ipware) by un33k.
166
+ - Built on top of [python-ipware](https://github.com/un33k/python-ipware) by un33k.
167
+ - https://github.com/long2ice/fastapi-limiter/blob/8d179c058fa2aaf98f3450c9026a7300ae2b3bdd/fastapi_limiter/__init__.py#L11
@@ -2,28 +2,28 @@
2
2
 
3
3
  A FastAPI/Starlette-native wrapper for [python-ipware](https://github.com/un33k/python-ipware) that eliminates the need for WSGI-style header conversion.
4
4
 
5
+ `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.
6
+
7
+ Also, 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. This is different from the
8
+ default ordering ipware which deprioritizes platform-specific headers, which is often the wrong ordering if you are using something like CloudFlare.
9
+
5
10
  ## Features
6
11
 
7
12
  - **Zero conversion overhead** - Headers converted once at initialization, not on every request
8
13
  - **FastAPI-native API** - Works directly with FastAPI/Starlette `Request` objects
9
14
  - **Customizable precedence** - Easy to configure header priority for your infrastructure
10
15
  - **Proxy validation** - Supports trusted proxy lists and proxy count validation
11
- - **Thin wrapper** - Leverages all the battle-tested logic from python-ipware
12
16
 
13
17
  ## Installation
14
18
 
15
- ```bash
16
- pip install fastapi-ipware
17
- ```
18
-
19
- Or with uv:
20
-
21
19
  ```bash
22
20
  uv add fastapi-ipware
23
21
  ```
24
22
 
25
23
  ## Quick Start
26
24
 
25
+ [Take a look at this example usage.](https://github.com/iloveitaly/structlog-config/blob/1e32f7afd206485b1356b322596cc19cb0bef8ba/structlog_config/fastapi_access_logger.py#L57-L72)
26
+
27
27
  ```python
28
28
  from fastapi import FastAPI, Request
29
29
  from fastapi_ipware import FastAPIIpWare
@@ -124,43 +124,6 @@ ipware = FastAPIIpWare(
124
124
  )
125
125
  ```
126
126
 
127
- ## Real-World Examples
128
-
129
- ### AWS Application Load Balancer
130
-
131
- ```python
132
- ipware = FastAPIIpWare(
133
- proxy_count=1,
134
- proxy_list=["10.0."] # Your VPC CIDR
135
- )
136
- ```
137
-
138
- ### Cloudflare
139
-
140
- ```python
141
- ipware = FastAPIIpWare(
142
- precedence=("CF-Connecting-IP",)
143
- )
144
- ```
145
-
146
- ### Multiple Proxies (CDN + Load Balancer)
147
-
148
- ```python
149
- ipware = FastAPIIpWare(
150
- proxy_count=2,
151
- proxy_list=["10.1.", "10.2."] # CDN and LB IPs
152
- )
153
- ```
154
-
155
- ### NGINX Reverse Proxy
156
-
157
- ```python
158
- ipware = FastAPIIpWare(
159
- precedence=("X-Real-IP", "X-Forwarded-For"),
160
- proxy_count=1
161
- )
162
- ```
163
-
164
127
  ## IP Address Types
165
128
 
166
129
  The returned IP address object has useful properties:
@@ -176,26 +139,16 @@ if ip:
176
139
  ```
177
140
 
178
141
  python-ipware automatically prefers:
142
+
179
143
  1. Public (global) IPs first
180
144
  2. Private IPs second
181
145
  3. Loopback IPs last
182
146
 
183
- ## Default Header Precedence
184
-
185
- 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.
186
-
187
- ## Why fastapi-ipware?
188
-
189
- `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.
190
-
191
- ## Contributing
192
-
193
- Contributions welcome! This is a thin wrapper around python-ipware, so most IP detection logic lives there.
194
-
195
147
  ## License
196
148
 
197
149
  [MIT License](LICENSE.md)
198
150
 
199
151
  ## Credits
200
152
 
201
- Built on top of [python-ipware](https://github.com/un33k/python-ipware) by un33k.
153
+ - Built on top of [python-ipware](https://github.com/un33k/python-ipware) by un33k.
154
+ - https://github.com/long2ice/fastapi-limiter/blob/8d179c058fa2aaf98f3450c9026a7300ae2b3bdd/fastapi_limiter/__init__.py#L11
@@ -65,18 +65,25 @@ class FastAPIIpWare(IpWare):
65
65
  # Generic headers (fallback)
66
66
  "X-Forwarded-For", # Generic, used by AWS ELB, nginx, etc.
67
67
  "X-Real-IP", # NGINX
68
- "Forwarded-For", # RFC 7239
69
- "Forwarded", # RFC 7239
68
+ # NOTE: Upstream python-ipware treats Forwarded headers as plain IP lists.
69
+ # RFC 7239 `Forwarded` parameters (for=) are not parsed.
70
+ "Forwarded-For", # RFC 7239 (plain IP list only)
71
+ "Forwarded", # RFC 7239 (plain IP list only)
70
72
  "Client-IP", # Akamai, Cloudflare
73
+ "REMOTE_ADDR", # Direct connection fallback
71
74
  )
72
75
 
73
76
  # Store FastAPI-style precedence for reference
74
77
  self._fastapi_precedence = precedence
75
78
 
76
- # Convert user-friendly header names (with dashes) to WSGI format once
77
- # This happens only at initialization, not on every request
79
+ # Convert user-friendly header names (with dashes) to WSGI format once.
80
+ # REMOTE_ADDR is a WSGI/ASGI convention, not an HTTP header, so it must
81
+ # not be prefixed with HTTP_.
78
82
  wsgi_precedence = tuple(
79
- f"HTTP_{header.upper().replace('-', '_')}" for header in precedence
83
+ "REMOTE_ADDR"
84
+ if header == "REMOTE_ADDR"
85
+ else f"HTTP_{header.upper().replace('-', '_')}"
86
+ for header in precedence
80
87
  )
81
88
 
82
89
  # Initialize parent class with WSGI-style headers
@@ -115,6 +122,11 @@ class FastAPIIpWare(IpWare):
115
122
  for name, value in request.headers.items()
116
123
  }
117
124
 
125
+ if request.client:
126
+ # NOTE: python-ipware falls back to REMOTE_ADDR when no headers match.
127
+ # Map Starlette's connection info to that expected key.
128
+ meta["REMOTE_ADDR"] = request.client.host
129
+
118
130
  return self.get_client_ip(meta, strict=strict)
119
131
 
120
132
 
@@ -1,21 +1,26 @@
1
1
  [project]
2
2
  name = "fastapi-ipware"
3
- version = "0.1.1"
3
+ version = "0.1.2"
4
4
  description = "FastAPI/Starlette-native wrapper for python-ipware to get client IP addresses"
5
- keywords = ["fastapi", "starlette", "ipware", "ip-address", "client-ip", "proxy", "x-forwarded-for"]
5
+ keywords = [
6
+ "fastapi",
7
+ "starlette",
8
+ "ipware",
9
+ "ip-address",
10
+ "client-ip",
11
+ "proxy",
12
+ "x-forwarded-for",
13
+ ]
6
14
  readme = "README.md"
7
15
  requires-python = ">=3.10"
8
- dependencies = [
9
- "python-ipware>=3.0.0",
10
- "starlette>=0.49.1",
11
- ]
16
+ dependencies = ["python-ipware>=3.0.0", "starlette>=0.49.1"]
12
17
  authors = [{ name = "Michael Bianco", email = "mike@mikebian.co" }]
13
18
  urls = { "Repository" = "https://github.com/iloveitaly/fastapi-ipware" }
14
19
 
15
20
  # additional packaging information: https://packaging.python.org/en/latest/specifications/core-metadata/#license
16
21
 
17
22
  [build-system]
18
- requires = ["uv_build>=0.8.11,<0.9.0"]
23
+ requires = ["uv_build>=0.9.0,<0.10.0"]
19
24
  build-backend = "uv_build"
20
25
 
21
26
  [tool.uv.build-backend]
@@ -23,8 +28,16 @@ build-backend = "uv_build"
23
28
  module-root = ""
24
29
 
25
30
  [dependency-groups]
26
- dev = ["pytest>=8.3.3","pyright>=1.1.380","ruff>=0.8.0"]
31
+ dev = [
32
+ "pytest>=8.3.3",
33
+ "pyright[nodejs]>=1.1.380",
34
+ "ruff>=0.8.0",
35
+ "fastapi>=0.128.0",
36
+ "httpx>=0.28.1",
37
+ ]
27
38
 
28
39
  [tool.pyright]
29
- exclude = ["example.py", ".venv", "**/__pycache__"]
40
+ exclude = ["examples/", "playground/", "tmp/", ".venv/", "tests/"]
30
41
 
42
+ [tool.ruff]
43
+ extend-exclude = ["playground.py", "playground/"]