• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Unleash / unleash-client-python / 11891936506

18 Nov 2024 11:57AM UTC coverage: 95.249% (-0.7%) from 95.923%
11891936506

Pull #330

github

sighphyre
fix: handle cases where the response from upstream is a valid 200 response but contains garbage
Pull Request #330: fix: handle cases where the response from upstream is a bad

3 of 8 new or added lines in 1 file covered. (37.5%)

401 of 421 relevant lines covered (95.25%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/UnleashClient/api/features.py
1
from typing import Optional, Tuple
1✔
2

3
import requests
1✔
4
from requests.adapters import HTTPAdapter
1✔
5
from urllib3 import Retry
1✔
6

7
from UnleashClient.constants import FEATURES_URL
1✔
8
from UnleashClient.utils import LOGGER, log_resp_info
1✔
9

10

11
# pylint: disable=broad-except
12
def get_feature_toggles(
1✔
13
    url: str,
14
    app_name: str,
15
    instance_id: str,
16
    custom_headers: dict,
17
    custom_options: dict,
18
    request_timeout: int,
19
    request_retries: int,
20
    project: Optional[str] = None,
21
    cached_etag: str = "",
22
) -> Tuple[str, str]:
23
    """
24
    Retrieves feature flags from unleash central server.
25

26
    Notes:
27
    * If unsuccessful (i.e. not HTTP status code 200), exception will be caught and logged.
28
      This is to allow "safe" error handling if unleash server goes down.
29

30
    :param url:
31
    :param app_name:
32
    :param instance_id:
33
    :param custom_headers:
34
    :param custom_options:
35
    :param request_timeout:
36
    :param request_retries:
37
    :param project:
38
    :param cached_etag:
39
    :return: (Feature flags, etag) if successful, ({},'') if not
40
    """
41
    try:
1✔
42
        LOGGER.info("Getting feature flag.")
1✔
43

44
        headers = {"UNLEASH-APPNAME": app_name, "UNLEASH-INSTANCEID": instance_id}
1✔
45

46
        if cached_etag:
1✔
47
            headers["If-None-Match"] = cached_etag
1✔
48

49
        base_url = f"{url}{FEATURES_URL}"
1✔
50
        base_params = {}
1✔
51

52
        if project:
1✔
53
            base_params = {"project": project}
1✔
54

55
        adapter = HTTPAdapter(
1✔
56
            max_retries=Retry(total=request_retries, status_forcelist=[500, 502, 504])
57
        )
58
        with requests.Session() as session:
1✔
59
            session.mount("https://", adapter)
1✔
60
            session.mount("http://", adapter)
1✔
61
            resp = session.get(
1✔
62
                base_url,
63
                headers={**custom_headers, **headers},
64
                params=base_params,
65
                timeout=request_timeout,
66
                **custom_options,
67
            )
68

69
        if resp.status_code not in [200, 304]:
1✔
70
            log_resp_info(resp)
1✔
71
            LOGGER.warning(
1✔
72
                "Unleash Client feature fetch failed due to unexpected HTTP status code."
73
            )
74
            raise Exception(
1✔
75
                "Unleash Client feature fetch failed!"
76
            )  # pylint: disable=broad-exception-raised
77

78
        etag = ""
1✔
79
        if "etag" in resp.headers.keys():
1✔
80
            etag = resp.headers["etag"]
1✔
81

82
        if resp.status_code == 304:
1✔
83
            return None, etag
1✔
84

85
        return resp.text, etag
1✔
86
    except Exception as exc:
1✔
87
        LOGGER.exception(
1✔
88
            "Unleash Client feature fetch failed due to exception: %s", exc
89
        )
90

91
    return None, ""
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc