Turing API

Django bot detection and email validation

Standard Django middleware plus a form validator, both fail-open so a network blip degrades to "allow" instead of a 500.

1. Install

pip install requests

2. Add the file

yourapp/middleware.py

import logging

import requests
from django.conf import settings
from django.http import JsonResponse

log = logging.getLogger(__name__)

TURING = "https://uat.turing-api.com"
PROTECTED_PREFIXES = ("/signup", "/api/")


def client_ip(request):
    forwarded = request.META.get("HTTP_X_FORWARDED_FOR", "")
    if forwarded:
        return forwarded.split(",")[0].strip()
    return request.META.get("REMOTE_ADDR", "")


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

    def __call__(self, request):
        if not request.path.startswith(PROTECTED_PREFIXES):
            return self.get_response(request)

        ip = client_ip(request)
        if not ip:
            return self.get_response(request)

        try:
            response = requests.post(
                TURING + "/v1/bot-check",
                headers={"Authorization": "Bearer " + settings.TURING_API_KEY},
                json={"ip": ip, "user_agent": request.META.get("HTTP_USER_AGENT", "")},
                timeout=3,
            )
            response.raise_for_status()
            verdict = response.json()
        except (requests.RequestException, ValueError) as error:
            log.warning("turing unreachable: %s", error)
            return self.get_response(request)  # fail open

        if verdict.get("is_bot") is True:
            return JsonResponse(
                {
                    "error": "Automated traffic is not permitted.",
                    "reasons": verdict.get("reasons", []),
                },
                status=403,
            )

        return self.get_response(request)

3. Wire it up

# settings.py
TURING_API_KEY = os.environ["TURING_API_KEY"]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "yourapp.middleware.BotCheckMiddleware",
    # ...
]

4. Verify

Confirm the API answers before you debug your Django wiring. The sample address sits inside a published AWS range, so a correct setup returns is_bot: true.

Notes

Other frameworks