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

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# 

12 

13import flask 

14from user_agents import parse 

15 

16from flipdare.app_log import LOG 

17from flipdare.constants import IS_TRACE, MAX_SUSPICION_SCORE 

18 

19__all__ = ["HttpUtil"] 

20 

21 

22class HttpUtil: 

23 @staticmethod 

24 def is_suspicious_request(req: flask.Request) -> bool: 

25 score = 0 

26 

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 

30 

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 

36 

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 

42 

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 

48 

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 

54 

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 

63 

64 return score >= MAX_SUSPICION_SCORE # suspicious if 2+ signals