11import hashlib
22import time
3+ import warnings
34from typing import Dict , List , Optional , Tuple
45
56from django .core .cache import cache as default_cache
67from django .core .exceptions import ImproperlyConfigured
78from django .http import HttpRequest
9+ from django .utils .module_loading import import_string
10+
11+
12+ def get_client_ip (request : HttpRequest ) -> Optional [str ]:
13+ """
14+ Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
15+ if present and number of proxies is > 0. If not use all of
16+ HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
17+ """
18+ from ninja .conf import settings
19+
20+ xff = request .META .get ("HTTP_X_FORWARDED_FOR" )
21+ remote_addr = request .META .get ("REMOTE_ADDR" )
22+ num_proxies = settings .NUM_PROXIES
23+
24+ if num_proxies is not None :
25+ if num_proxies == 0 or xff is None :
26+ return remote_addr
27+ addrs : List [str ] = xff .split ("," )
28+ client_addr = addrs [- min (num_proxies , len (addrs ))]
29+ return client_addr .strip ()
30+
31+ return "" .join (xff .split ()) if xff else remote_addr
832
933
1034class BaseThrottle :
1135 """
1236 Rate throttling of requests.
1337 """
1438
39+ def __init__ (self ) -> None :
40+ from ninja .conf import settings
41+
42+ self .client_ip = import_string (settings .CLIENT_IP_CALLABLE )
43+
1544 def allow_request (self , request : HttpRequest ) -> bool :
1645 """
1746 Return `True` if the request should be allowed, `False` otherwise.
1847 """
1948 raise NotImplementedError (".allow_request() must be overridden" )
2049
2150 def get_ident (self , request : HttpRequest ) -> Optional [str ]:
22- """
23- Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
24- if present and number of proxies is > 0. If not use all of
25- HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
26- """
27- from ninja .conf import settings
28-
29- xff = request .META .get ("HTTP_X_FORWARDED_FOR" )
30- remote_addr = request .META .get ("REMOTE_ADDR" )
31- num_proxies = settings .NUM_PROXIES
32-
33- if num_proxies is not None :
34- if num_proxies == 0 or xff is None :
35- return remote_addr
36- addrs : List [str ] = xff .split ("," )
37- client_addr = addrs [- min (num_proxies , len (addrs ))]
38- return client_addr .strip ()
39-
40- return "" .join (xff .split ()) if xff else remote_addr
51+ warnings .warn (
52+ ".get_ident() is deprecated, use .client_ip() instead" ,
53+ DeprecationWarning ,
54+ stacklevel = 2 ,
55+ )
56+ return get_client_ip (request )
4157
4258 def wait (self ) -> Optional [float ]:
4359 """
@@ -79,6 +95,7 @@ class SimpleRateThrottle(BaseThrottle):
7995 }
8096
8197 def __init__ (self , rate : Optional [str ] = None ):
98+ super ().__init__ ()
8299 self .rate : Optional [str ]
83100 if rate :
84101 self .rate = rate
@@ -204,7 +221,7 @@ def get_cache_key(self, request: HttpRequest) -> Optional[str]:
204221
205222 return self .cache_format % {
206223 "scope" : self .scope ,
207- "ident" : self .get_ident (request ),
224+ "ident" : self .client_ip (request ),
208225 }
209226
210227
@@ -224,7 +241,7 @@ def get_cache_key(self, request: HttpRequest) -> str:
224241 ident = hashlib .sha256 (str (request .auth ).encode ()).hexdigest () # type: ignore
225242 # TODO: ^maybe auth should have an attribute that developer can overwrite
226243 else :
227- ident = self .get_ident (request ) # type: ignore
244+ ident = self .client_ip (request ) # type: ignore
228245
229246 return self .cache_format % {"scope" : self .scope , "ident" : ident }
230247
@@ -244,6 +261,6 @@ def get_cache_key(self, request: HttpRequest) -> str:
244261 if request .user and request .user .is_authenticated :
245262 ident = request .user .pk
246263 else :
247- ident = self .get_ident (request )
264+ ident = self .client_ip (request )
248265
249266 return self .cache_format % {"scope" : self .scope , "ident" : ident }
0 commit comments