Skip to content

Commit

Permalink
Merge pull request #220 from jsocol/empty-ip
Browse files Browse the repository at this point in the history
Add clearer exception on misconfigured REMOTE_ADDR
  • Loading branch information
jsocol authored Jan 25, 2021
2 parents 298d4f3 + ec7b1b3 commit 4980d17
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Minor changes:
--------------

- Factor up _get_ip() logic into a single place (#218)
- Exception on empty REMOTE_ADDR is clearer (#220)

3.0.1
=====
Expand Down
30 changes: 18 additions & 12 deletions ratelimit/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,24 @@
def _get_ip(request):
ip_meta = getattr(settings, 'RATELIMIT_IP_META_KEY', None)
if not ip_meta:
return request.META['REMOTE_ADDR']
if callable(ip_meta):
return ip_meta(request)
if isinstance(ip_meta, str) and '.' in ip_meta:
ip = request.META['REMOTE_ADDR']
if not ip:
raise ImproperlyConfigured(
'IP address in REMOTE_ADDR is empty. This can happen when '
'using a reverse proxy and connecting to the app server with '
'Unix sockets. See the documentation for '
'RATELIMIT_IP_META_KEY: https://bit.ly/3iIpy2x')
elif callable(ip_meta):
ip = ip_meta(request)
elif isinstance(ip_meta, str) and '.' in ip_meta:
ip_meta_fn = import_string(ip_meta)
return ip_meta_fn(request)
if ip_meta in request.META:
return request.META[ip_meta]
raise ImproperlyConfigured('Could not get IP address from "%s"' % ip_meta)

ip = ip_meta_fn(request)
elif ip_meta in request.META:
ip = request.META[ip_meta]
else:
raise ImproperlyConfigured(
'Could not get IP address from "%s"' % ip_meta)

def ip_mask(ip):
if ':' in ip:
# IPv6
mask = getattr(settings, 'RATELIMIT_IPV6_MASK', 64)
Expand All @@ -56,11 +62,11 @@ def ip_mask(ip):
def user_or_ip(request):
if request.user.is_authenticated:
return str(request.user.pk)
return ip_mask(_get_ip(request))
return _get_ip(request)


_SIMPLE_KEYS = {
'ip': lambda r: ip_mask(_get_ip(r)),
'ip': lambda r: _get_ip(r),
'user': lambda r: str(r.user.pk),
'user_or_ip': user_or_ip,
}
Expand Down
7 changes: 7 additions & 0 deletions ratelimit/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,3 +622,10 @@ def test_callable_ip_key(self):
req.META['MY_THING'] = '5.6.7.8'

assert '5.6.7.8' == _get_ip(req)

def test_empty_ip(self):
req = rf.get('/')
req.META['REMOTE_ADDR'] = ''

with self.assertRaises(ImproperlyConfigured):
_get_ip(req)

0 comments on commit 4980d17

Please sign in to comment.