From d4b4d04fb962c16df8eafa71bd957094e20626a3 Mon Sep 17 00:00:00 2001 From: MEHRSHAD MIRSHEKARY Date: Sat, 17 Aug 2024 21:13:32 +0330 Subject: [PATCH] :sparkles::bulb: feat(middleware):add request middleware to log user detail from request introduced RequestLogMiddleware, that captures and logs additional information about users who send requests to the server. The logged information includes: IP Address: Retrieved from the request object using the get_ip_address method, which checks for the HTTP_X_FORWARDED_FOR header and falls back to the REMOTE_ADDR header if not present. Browser Type: Extracted from the HTTP_USER_AGENT header using the get_user_agent method, which returns a default value of 'Unknown User Agent' if the header is not present. Additional metadata: Includes other relevant information, such as operating system, device type, or any custom user attributes. The middleware integrates seamlessly into the request lifecycle by calling the get_response method to get the response from the view function, and then logging the request information using the logger object. Closes #6 --- django_logging/middleware/__init__.py | 1 + .../middleware/request_middleware.py | 84 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 django_logging/middleware/__init__.py create mode 100644 django_logging/middleware/request_middleware.py diff --git a/django_logging/middleware/__init__.py b/django_logging/middleware/__init__.py new file mode 100644 index 0000000..53d0413 --- /dev/null +++ b/django_logging/middleware/__init__.py @@ -0,0 +1 @@ +from .request_middleware import RequestLogMiddleware diff --git a/django_logging/middleware/request_middleware.py b/django_logging/middleware/request_middleware.py new file mode 100644 index 0000000..b523f2f --- /dev/null +++ b/django_logging/middleware/request_middleware.py @@ -0,0 +1,84 @@ +import logging +from django.contrib.auth import get_user_model +from django.http import HttpResponse, HttpRequest +from typing import Callable + +logger = logging.getLogger(__name__) + + +class RequestLogMiddleware: + """ + Middleware to log information about each incoming request. + + This middleware logs the request path, the user making the request (if authenticated), + and the user's IP address. + """ + + def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]) -> None: + """ + Initializes the RequestLogMiddleware instance. + + Args: + get_response: A callable that returns an HttpResponse object. + """ + self.get_response = get_response + user_model = get_user_model() + self.username_field = user_model.USERNAME_FIELD + + def __call__(self, request: HttpRequest) -> HttpResponse: + """ + Processes an incoming request and logs relevant information. + + Args: + request: The incoming request object. + + Returns: + The response object returned by the view function. + """ + # Before view (and later middleware) are called. + response = self.get_response(request) + + # After view is called. + if hasattr(request, "user") and request.user.is_authenticated: + user = getattr(request.user, self.username_field, "Anonymous") + else: + user = "Anonymous" + + # Get the user's IP address + ip_address = self.get_ip_address(request) + + # Get the user agent + user_agent = self.get_user_agent(request) + + # Attach IP and user agent to the request + request.ip_address = ip_address + request.browser_type = user_agent + + logger.info( + f"Request Info: (request_path: {request.path}, user: {user}," + f"\nIP: {ip_address}, user_agent: {user_agent})" + ) + + return response + + @staticmethod + def get_ip_address(request: HttpRequest) -> str: + """ + Retrieves the client's IP address from the request object. + """ + ip_address = request.META.get("HTTP_X_FORWARDED_FOR") + if ip_address: + ip_address = ip_address.split(",")[0] + else: + ip_address = request.META.get("LIMITED_ACCESS") + if not ip_address: + ip_address = request.META.get("REMOTE_ADDR") + + return ip_address + + @staticmethod + def get_user_agent(request: HttpRequest) -> str: + """ + Retrieves the client's user agent from the request object. + """ + return request.META.get("HTTP_USER_AGENT", "Unknown User Agent")