Coverage for functions \ flipdare \ util \ http_util.py: 91%
34 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
13import flask
14from user_agents import parse
16from flipdare.app_log import LOG
17from flipdare.constants import IS_TRACE, MAX_SUSPICION_SCORE
19__all__ = ["HttpUtil"]
22class HttpUtil:
23 @staticmethod
24 def is_suspicious_request(req: flask.Request) -> bool:
25 score = 0
27 ua_string = req.headers.get("User-Agent", "")
28 ua = parse(ua_string)
29 url_str = req.url if hasattr(req, "url") else req.path
31 # 1. Missing UA
32 if not ua_string:
33 if IS_TRACE:
34 LOG().trace(f"Suspicious request {url_str} - missing User-Agent")
35 score += 1
37 # 2. Bot or crawler
38 if ua.is_bot:
39 if IS_TRACE:
40 LOG().trace(f"Suspicious request {url_str} - detected bot or crawler")
41 score += 1
43 # 3. Missing Accept header
44 if not req.headers.get("Accept"):
45 if IS_TRACE:
46 LOG().trace(f"Suspicious request {url_str} - missing Accept header")
47 score += 1
49 # 4. Missing Accept-Language
50 if not req.headers.get("Accept-Language"):
51 if IS_TRACE:
52 LOG().trace(f"Suspicious request {url_str} - missing Accept-Language header")
53 score += 1
55 # 5. Known automation signatures
56 bad_sigs = ["curl", "python-requests", "go-http-client", "java"]
57 if any(sig in ua_string.lower() for sig in bad_sigs):
58 if IS_TRACE:
59 LOG().trace(
60 f"Suspicious request {url_str} - User-Agent contains automation signature"
61 )
62 score += 2 # automation signatures are a stronger signal, so we add 2 points
64 return score >= MAX_SUSPICION_SCORE # suspicious if 2+ signals