vpndetection-fastapi 2.0.7__tar.gz → 2.0.9__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.
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/CHANGELOG.md +12 -0
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/PKG-INFO +5 -3
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/README.md +3 -1
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/pyproject.toml +1 -1
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/src/vpndetection_fastapi/__init__.py +1 -1
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/testdata/bogons.json +30 -4
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/testdata/testdata.json +52 -6
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/.github/workflows/ci.yml +0 -0
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/.github/workflows/release.yml +0 -0
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/.gitignore +0 -0
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/LICENSE +0 -0
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/src/vpndetection_fastapi/py.typed +0 -0
- {vpndetection_fastapi-2.0.7 → vpndetection_fastapi-2.0.9}/tests/test_middleware.py +0 -0
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
What each release changed for you, newest first. Each line is a commit's summary, linked to its full description and diff. Releases before 2.0.5 are described by their release commits.
|
|
4
4
|
|
|
5
|
+
## 2.0.9 - 2026-10-02
|
|
6
|
+
|
|
7
|
+
### Fixes
|
|
8
|
+
|
|
9
|
+
- Require vpndetection 5.5.3: a long Retry-After or timeout no longer raises OverflowError ([`7805671`](https://github.com/vpndetection-io/sdk-python-fastapi/commit/78056714706cbadef865a8b1888209fae061a796))
|
|
10
|
+
|
|
11
|
+
## 2.0.8 - 2026-09-29
|
|
12
|
+
|
|
13
|
+
### Fixes
|
|
14
|
+
|
|
15
|
+
- Require vpndetection 5.5.2: 26 more reserved ranges are answered locally ([`73b34b6`](https://github.com/vpndetection-io/sdk-python-fastapi/commit/73b34b6ca355cc56fcfcbf159a241ec114541c78))
|
|
16
|
+
|
|
5
17
|
## 2.0.7 - 2026-09-28
|
|
6
18
|
|
|
7
19
|
### Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vpndetection-fastapi
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.9
|
|
4
4
|
Summary: Official FastAPI and Starlette middleware for the VPNDetection API. Detect VPNs, proxies, Tor, hosting and CDN visitors on every request.
|
|
5
5
|
Project-URL: Homepage, https://vpndetection.io
|
|
6
6
|
Project-URL: Source, https://github.com/vpndetection-io/sdk-python-fastapi
|
|
@@ -20,7 +20,7 @@ Classifier: Topic :: Security
|
|
|
20
20
|
Classifier: Typing :: Typed
|
|
21
21
|
Requires-Python: >=3.11
|
|
22
22
|
Requires-Dist: starlette>=0.37
|
|
23
|
-
Requires-Dist: vpndetection<6,>=5.5.
|
|
23
|
+
Requires-Dist: vpndetection<6,>=5.5.3
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
26
26
|
Requires-Dist: pytest>=8; extra == 'dev'
|
|
@@ -67,6 +67,8 @@ async def index(request: Request):
|
|
|
67
67
|
return {"vpn": found.result.is_vpn}
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
A request your `skip` claims gets no answer, and `lookup(request)` is `None` for it.
|
|
71
|
+
|
|
70
72
|
By default nothing is blocked. Every request gets an answer and your own code decides what that means — which is usually what you want, because whether a VPN visitor is a problem depends entirely on what they are doing.
|
|
71
73
|
|
|
72
74
|
## Blocking
|
|
@@ -124,7 +126,7 @@ Skip what you do not care about:
|
|
|
124
126
|
skip = lambda request: request.url.path.startswith("/static")
|
|
125
127
|
```
|
|
126
128
|
|
|
127
|
-
Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io
|
|
129
|
+
Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io/#databases) and look addresses up locally instead.
|
|
128
130
|
|
|
129
131
|
## Absent is not false
|
|
130
132
|
|
|
@@ -38,6 +38,8 @@ async def index(request: Request):
|
|
|
38
38
|
return {"vpn": found.result.is_vpn}
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
A request your `skip` claims gets no answer, and `lookup(request)` is `None` for it.
|
|
42
|
+
|
|
41
43
|
By default nothing is blocked. Every request gets an answer and your own code decides what that means — which is usually what you want, because whether a VPN visitor is a problem depends entirely on what they are doing.
|
|
42
44
|
|
|
43
45
|
## Blocking
|
|
@@ -95,7 +97,7 @@ Skip what you do not care about:
|
|
|
95
97
|
skip = lambda request: request.url.path.startswith("/static")
|
|
96
98
|
```
|
|
97
99
|
|
|
98
|
-
Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io
|
|
100
|
+
Beyond a few million distinct visitors a day, stop calling the API per request: [download the dataset](https://vpndetection.io/#databases) and look addresses up locally instead.
|
|
99
101
|
|
|
100
102
|
## Absent is not false
|
|
101
103
|
|
|
@@ -8,53 +8,79 @@
|
|
|
8
8
|
"172.16.0.0/12",
|
|
9
9
|
"192.0.0.0/24",
|
|
10
10
|
"192.0.2.0/24",
|
|
11
|
+
"192.88.99.2/32",
|
|
11
12
|
"192.168.0.0/16",
|
|
12
13
|
"198.18.0.0/15",
|
|
13
14
|
"198.51.100.0/24",
|
|
14
15
|
"203.0.113.0/24",
|
|
15
16
|
"224.0.0.0/4",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
17
|
+
"255.255.255.255/32",
|
|
18
|
+
"240.0.0.0/4"
|
|
18
19
|
],
|
|
19
20
|
"v6": [
|
|
20
21
|
"::/128",
|
|
21
22
|
"::1/128",
|
|
22
23
|
"::ffff:0:0/96",
|
|
23
24
|
"::/96",
|
|
25
|
+
"64:ff9b::/96",
|
|
26
|
+
"64:ff9b:1::/48",
|
|
24
27
|
"100::/64",
|
|
28
|
+
"100:0:0:1::/64",
|
|
29
|
+
"2001:2::/48",
|
|
25
30
|
"2001:10::/28",
|
|
26
31
|
"2001:db8::/32",
|
|
32
|
+
"3fff::/20",
|
|
33
|
+
"5f00::/16",
|
|
27
34
|
"fc00::/7",
|
|
28
35
|
"fe80::/10",
|
|
29
36
|
"fec0::/10",
|
|
30
37
|
"ff00::/8",
|
|
31
38
|
"2002::/24",
|
|
32
39
|
"2002:a00::/24",
|
|
40
|
+
"2002:6440::/26",
|
|
33
41
|
"2002:7f00::/24",
|
|
34
42
|
"2002:a9fe::/32",
|
|
35
43
|
"2002:ac10::/28",
|
|
36
44
|
"2002:c000::/40",
|
|
37
45
|
"2002:c000:200::/40",
|
|
46
|
+
"2002:c058:6302::/48",
|
|
38
47
|
"2002:c0a8::/32",
|
|
39
48
|
"2002:c612::/31",
|
|
40
49
|
"2002:c633:6400::/40",
|
|
41
50
|
"2002:cb00:7100::/40",
|
|
42
51
|
"2002:e000::/20",
|
|
43
|
-
"2002:f000::/20",
|
|
44
52
|
"2002:ffff:ffff::/48",
|
|
53
|
+
"2002:f000::/20",
|
|
45
54
|
"2001::/40",
|
|
46
55
|
"2001:0:a00::/40",
|
|
56
|
+
"2001:0:6440::/42",
|
|
47
57
|
"2001:0:7f00::/40",
|
|
48
58
|
"2001:0:a9fe::/48",
|
|
49
59
|
"2001:0:ac10::/44",
|
|
50
60
|
"2001:0:c000::/56",
|
|
51
61
|
"2001:0:c000:200::/56",
|
|
62
|
+
"2001:0:c058:6302::/64",
|
|
52
63
|
"2001:0:c0a8::/48",
|
|
53
64
|
"2001:0:c612::/47",
|
|
54
65
|
"2001:0:c633:6400::/56",
|
|
55
66
|
"2001:0:cb00:7100::/56",
|
|
56
67
|
"2001:0:e000::/36",
|
|
68
|
+
"2001:0:ffff:ffff::/64",
|
|
57
69
|
"2001:0:f000::/36",
|
|
58
|
-
"2001:
|
|
70
|
+
"2001:1::/32",
|
|
71
|
+
"2001:2::/31",
|
|
72
|
+
"2001:4::/30",
|
|
73
|
+
"2001:8::/29",
|
|
74
|
+
"2001:20::/27",
|
|
75
|
+
"2001:40::/26",
|
|
76
|
+
"2001:80::/25",
|
|
77
|
+
"2001:100::/24",
|
|
78
|
+
"::/3",
|
|
79
|
+
"4000::/3",
|
|
80
|
+
"6000::/3",
|
|
81
|
+
"8000::/3",
|
|
82
|
+
"a000::/3",
|
|
83
|
+
"c000::/3",
|
|
84
|
+
"e000::/3"
|
|
59
85
|
]
|
|
60
86
|
}
|
|
@@ -137,8 +137,18 @@
|
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
"ip": "fe00::",
|
|
140
|
+
"expect": true,
|
|
141
|
+
"why": "past fc00::/7 but inside e000::/3, outside global unicast"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"ip": "3fff:fff:ffff:ffff:ffff:ffff:ffff:ffff",
|
|
145
|
+
"expect": true,
|
|
146
|
+
"why": "last address inside 3fff::/20; pins the /20 mask width"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"ip": "3fff:1000::",
|
|
140
150
|
"expect": false,
|
|
141
|
-
"why": "first address past
|
|
151
|
+
"why": "first address past 3fff::/20; a mask one bit too wide claims it"
|
|
142
152
|
},
|
|
143
153
|
{
|
|
144
154
|
"ip": "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff",
|
|
@@ -177,8 +187,18 @@
|
|
|
177
187
|
},
|
|
178
188
|
{
|
|
179
189
|
"ip": "100:0:0:1::",
|
|
190
|
+
"expect": true,
|
|
191
|
+
"why": "past 100::/64 but inside 100:0:0:1::/64 and ::/3"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"ip": "2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff",
|
|
195
|
+
"expect": true,
|
|
196
|
+
"why": "last address inside 2001::/23; pins the /23 mask width"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"ip": "2001:200::",
|
|
180
200
|
"expect": false,
|
|
181
|
-
"why": "first address past
|
|
201
|
+
"why": "first address past 2001::/23; a mask one bit too wide claims it"
|
|
182
202
|
},
|
|
183
203
|
{
|
|
184
204
|
"ip": "10.255.255.255",
|
|
@@ -6645,54 +6665,80 @@
|
|
|
6645
6665
|
"172.16.0.0/12",
|
|
6646
6666
|
"192.0.0.0/24",
|
|
6647
6667
|
"192.0.2.0/24",
|
|
6668
|
+
"192.88.99.2/32",
|
|
6648
6669
|
"192.168.0.0/16",
|
|
6649
6670
|
"198.18.0.0/15",
|
|
6650
6671
|
"198.51.100.0/24",
|
|
6651
6672
|
"203.0.113.0/24",
|
|
6652
6673
|
"224.0.0.0/4",
|
|
6653
|
-
"
|
|
6654
|
-
"
|
|
6674
|
+
"255.255.255.255/32",
|
|
6675
|
+
"240.0.0.0/4"
|
|
6655
6676
|
],
|
|
6656
6677
|
"v6": [
|
|
6657
6678
|
"::/128",
|
|
6658
6679
|
"::1/128",
|
|
6659
6680
|
"::ffff:0:0/96",
|
|
6660
6681
|
"::/96",
|
|
6682
|
+
"64:ff9b::/96",
|
|
6683
|
+
"64:ff9b:1::/48",
|
|
6661
6684
|
"100::/64",
|
|
6685
|
+
"100:0:0:1::/64",
|
|
6686
|
+
"2001:2::/48",
|
|
6662
6687
|
"2001:10::/28",
|
|
6663
6688
|
"2001:db8::/32",
|
|
6689
|
+
"3fff::/20",
|
|
6690
|
+
"5f00::/16",
|
|
6664
6691
|
"fc00::/7",
|
|
6665
6692
|
"fe80::/10",
|
|
6666
6693
|
"fec0::/10",
|
|
6667
6694
|
"ff00::/8",
|
|
6668
6695
|
"2002::/24",
|
|
6669
6696
|
"2002:a00::/24",
|
|
6697
|
+
"2002:6440::/26",
|
|
6670
6698
|
"2002:7f00::/24",
|
|
6671
6699
|
"2002:a9fe::/32",
|
|
6672
6700
|
"2002:ac10::/28",
|
|
6673
6701
|
"2002:c000::/40",
|
|
6674
6702
|
"2002:c000:200::/40",
|
|
6703
|
+
"2002:c058:6302::/48",
|
|
6675
6704
|
"2002:c0a8::/32",
|
|
6676
6705
|
"2002:c612::/31",
|
|
6677
6706
|
"2002:c633:6400::/40",
|
|
6678
6707
|
"2002:cb00:7100::/40",
|
|
6679
6708
|
"2002:e000::/20",
|
|
6680
|
-
"2002:f000::/20",
|
|
6681
6709
|
"2002:ffff:ffff::/48",
|
|
6710
|
+
"2002:f000::/20",
|
|
6682
6711
|
"2001::/40",
|
|
6683
6712
|
"2001:0:a00::/40",
|
|
6713
|
+
"2001:0:6440::/42",
|
|
6684
6714
|
"2001:0:7f00::/40",
|
|
6685
6715
|
"2001:0:a9fe::/48",
|
|
6686
6716
|
"2001:0:ac10::/44",
|
|
6687
6717
|
"2001:0:c000::/56",
|
|
6688
6718
|
"2001:0:c000:200::/56",
|
|
6719
|
+
"2001:0:c058:6302::/64",
|
|
6689
6720
|
"2001:0:c0a8::/48",
|
|
6690
6721
|
"2001:0:c612::/47",
|
|
6691
6722
|
"2001:0:c633:6400::/56",
|
|
6692
6723
|
"2001:0:cb00:7100::/56",
|
|
6693
6724
|
"2001:0:e000::/36",
|
|
6725
|
+
"2001:0:ffff:ffff::/64",
|
|
6694
6726
|
"2001:0:f000::/36",
|
|
6695
|
-
"2001:
|
|
6727
|
+
"2001:1::/32",
|
|
6728
|
+
"2001:2::/31",
|
|
6729
|
+
"2001:4::/30",
|
|
6730
|
+
"2001:8::/29",
|
|
6731
|
+
"2001:20::/27",
|
|
6732
|
+
"2001:40::/26",
|
|
6733
|
+
"2001:80::/25",
|
|
6734
|
+
"2001:100::/24",
|
|
6735
|
+
"::/3",
|
|
6736
|
+
"4000::/3",
|
|
6737
|
+
"6000::/3",
|
|
6738
|
+
"8000::/3",
|
|
6739
|
+
"a000::/3",
|
|
6740
|
+
"c000::/3",
|
|
6741
|
+
"e000::/3"
|
|
6696
6742
|
]
|
|
6697
6743
|
}
|
|
6698
6744
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|