Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to use python-ipware #358

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions django_structlog/middlewares/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ def get_request_header(request, header_key, meta_key):

return request.META.get(meta_key)

def get_client_ip(request):
from ipware import IpWare

# Instantiate IpWare with default values
ipw = IpWare()
Comment on lines +23 to +26
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this moved on the top of the file?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it has to be added to app_settings.py and be configurable through settings.


# Get the request headers for Django 4.0
if hasattr(request, "headers"):
meta = request.headers

# Get the request headers for Django < 4
else:
meta = request.META
jrobichaud marked this conversation as resolved.
Show resolved Hide resolved

# Get the client IP
ip, _ = ipw.get_client_ip(meta)

# Cast IP to string
return str(ip), _

class BaseRequestMiddleWare:
def __init__(self, get_response):
Expand Down Expand Up @@ -57,9 +76,8 @@ def handle_response(self, request, response):
)
structlog.contextvars.clear_contextvars()

def prepare(self, request):
from ipware import get_client_ip

def prepare(self, request):
request_id = get_request_header(
request, "x-request-id", "HTTP_X_REQUEST_ID"
) or str(uuid.uuid4())
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ build-backend = "setuptools.build_meta"
"django>=3.2",
"structlog>=21.4.0",
"asgiref>=3.6.0",
"django-ipware",
"python-ipware",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
Expand Down
2 changes: 1 addition & 1 deletion requirements/local-base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ coreapi==2.3.3 # https://github.com/core-api/python-client

structlog==23.2.0
colorama==0.4.6
django-ipware==5.0.1
python-ipware==1.0.5 # https://github.com/un33k/python-ipware

Werkzeug==3.0.0 # https://github.com/pallets/werkzeug
ipdb==0.13.13 # https://github.com/gotcha/ipdb
Expand Down
24 changes: 24 additions & 0 deletions test_app/tests/middlewares/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,30 @@ def get_response(_response):
self.assertNotIn("user_id", record.msg)
self.assertEqual(x_correlation_id, record.msg["correlation_id"])

def test_should_log_remote_ip(self):
mock_response = Mock()
mock_response.status_code = 200
x_forwarded_for = "123.123.123.1"

def get_response(_response):
with self.assertLogs(__name__, logging.INFO) as log_results:
self.logger.info("hello")
self.log_results = log_results
return mock_response

request = RequestFactory(HTTP_X_FORWARDED_FOR=x_forwarded_for).get("/foo")

middleware = middlewares.RequestMiddleware(get_response)
middleware(request)

self.assertEqual(1, len(self.log_results.records))
record = self.log_results.records[0]

self.assertEqual("INFO", record.levelname)
self.assertIn("request_id", record.msg)
self.assertNotIn("user_id", record.msg)
self.assertEqual(x_forwarded_for, record.msg["ip"])


class TestRequestMiddlewareRouter(TestCase):
async def test_async(self):
Expand Down