[Django]-How can I catch django.http.request.DisallowedHost in a view?

5👍

Please don’t replace middleware or do some other weird stuff. It’s very simple: DisallowedHost() is raised by the first thing that calls get_host() on a request object. Typically, this is a middleware, because doing it too early in the request/response cycle would make it impossible to turn off or customize.

So inject your custom middleware first in the chain and shortcircuit things there:

# File: main.middleware
from django.shortcuts import redirect
from django.core.exceptions import DisallowedHost


class FriendlyDisallowedHost:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request, *args, **kwargs):
        try:
            checkhost = request.get_host()
        except DisallowedHost:
            return redirect("http://localhost/")
        
        return self.get_response(request)

settings:

MIDDLEWARE = [
    "main.middleware.FriendlyDisallowedHost",
    # ... rest of middleware
]

0👍

You can use custom middleware for this.

For that, create a custom middleware by sub-classing the CommonMiddleware–(Doc) class and override the process_request(...)–(Doc) method

# some_place/some_module.py

from django.middleware.common import CommonMiddleware
from django.core.exceptions import DisallowedHost
from django.http.response import HttpResponse
from django.shortcuts import render


class CustomCommonMiddleware(CommonMiddleware):
    def process_request(self, request):
        try:
            return super().process_request(request)
        except DisallowedHost:
            return render(request, 'something.html')

Then, replace the django.middleware.common.CommonMiddleware middleware with the newly created custom class in MIDDLEWARE-(Doc) settings as,

# settings.py

MIDDLEWARE = [
    # other middleware
    'some_place.some_module.CustomCommonMiddleware', # add this
    'django.middleware.common.CommonMiddleware', # Remove this
    # other middleware
]
👤JPG

0👍

Because Django will intercept the request and raise this exception before it even calls your view, you should use a custom error view for handling these kinds of errors overriding the default error views

In your application view, write the handler you want for handling DisallowedHost

from django.views.defaults import bad_request as default_bad_request
from django.core.exceptions import DisallowedHost
from django.http import HttpResponse


def my_bad_request_handler(request, exception=None, **kwargs):
    if isinstance(exception, DisallowedHost):
        return HttpResponse("This server is not configured for this hostname", status=400)
    # if it's some other kind of bad request, use Django's default handler
    return default_bad_request(request, exception, **kwargs)

Then in your URLConf set the 400 handler to your custom view:

handler400 = 'mysite.views.my_bad_request_handler'

See also: SuspiciousOperation exception and 400 bad request view.

👤sytech

Leave a comment