From 414a868c38da2114fcf16dc04f4b6a7a02ef10ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E8=97=A4=E4=BD=B3=E6=B1=B0?= Date: Thu, 21 May 2026 10:45:53 +0900 Subject: [PATCH] Add X-SaaSus-Trace-Id auto-propagation feature - Add x_saasus_trace_id field to Client singleton - Inject X-SaaSus-Trace-Id header in set_referer_header() - Propagate through Authenticate.authenticate() and all API client constructors - Extract X-SaaSus-Trace-Id from incoming request in fastapi_auth() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- saasus_sdk_python/.DS_Store | Bin 0 -> 6148 bytes saasus_sdk_python/__main__.py | 3 ++- saasus_sdk_python/client/apilog_client.py | 3 ++- saasus_sdk_python/client/auth_client.py | 3 ++- .../client/awsmarketplace_client.py | 3 ++- saasus_sdk_python/client/billing_client.py | 3 ++- saasus_sdk_python/client/client.py | 3 +++ saasus_sdk_python/client/communication_client.py | 3 ++- saasus_sdk_python/client/integration_client.py | 3 ++- saasus_sdk_python/client/pricing_client.py | 3 ++- saasus_sdk_python/middleware/middleware.py | 3 ++- test/.DS_Store | Bin 0 -> 8196 bytes 12 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 saasus_sdk_python/.DS_Store create mode 100644 test/.DS_Store diff --git a/saasus_sdk_python/.DS_Store b/saasus_sdk_python/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..cadbfcdd3503a8bbff7942537a2c307a675eeafa GIT binary patch literal 6148 zcmeHKJ5Izf5FIZo6kv<(pv)E0QiUjVbh!YV&5A`NWQ9PK^Iz!iAo zvGO5_*a{&u6WK2rkL{P|C}R_miSDw1Xih{P3gcuC)qrt3m!3_WX9hHOjFc9%q^tZQ zNP5xg_=^hg+Id*B1?9L}>$fb6jS!w455*K^9H)7ia@*(Q^Wnq$+sSZTwpH9_9VE@1 z{5{exc;$3SE4rpz{-&Dtv*>$!o6plr&8IU)Q8rx0V!Avk=CMx&SY)_zaJh$8H?->V z@jk}l+Putb&1-PXHou=@yF9I4%vDVlPz6+hZ4^MxX7dgNwN?dG0ac(@fd3CZ3S;Q7 z612Y#RQ3n}oWgAl_jWG=^w|Ln9ae(yz>IVSN>}5K7)H9o@4L9rVI?Tt$=I1Oj+@!I z6N+&=A>-R{GNGW>s(>ocRbWRR=bZmf$It)WPWq$@r~>~=0W*!0IKnHr+}e9N&b2 Union[dict, HTTPException]: auth_header = request.headers.get("Authorization", "") token = auth_header.replace("Bearer ", "") if "Bearer " in auth_header else "" referer = request.headers.get("Referer", "") - user_info, error = auth.authenticate(id_token=token, referer=referer) + x_saasus_trace_id = request.headers.get("X-SaaSus-Trace-Id", "") + user_info, error = auth.authenticate(id_token=token, referer=referer, x_saasus_trace_id=x_saasus_trace_id) if error: raise HTTPException(status_code=401, detail=str(error)) return user_info diff --git a/saasus_sdk_python/client/apilog_client.py b/saasus_sdk_python/client/apilog_client.py index 957c65a..5089300 100644 --- a/saasus_sdk_python/client/apilog_client.py +++ b/saasus_sdk_python/client/apilog_client.py @@ -6,12 +6,13 @@ class SignedApilogApiClient(ApiClient): - def __init__(self, referer=None, x_saasus_referer=None, *args, **kwargs): + def __init__(self, referer=None, x_saasus_referer=None, x_saasus_trace_id=None, *args, **kwargs): super().__init__(*args, **kwargs) self.client = Client() self.configuration.default_headers = {} self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id self.base_url = os.getenv("SAASUS_BASE_URL", "https://api.saasus.io/v1") def call_api(self, resource_path, method, diff --git a/saasus_sdk_python/client/auth_client.py b/saasus_sdk_python/client/auth_client.py index 600a11d..7275ac9 100644 --- a/saasus_sdk_python/client/auth_client.py +++ b/saasus_sdk_python/client/auth_client.py @@ -6,10 +6,11 @@ class SignedAuthApiClient(ApiClient): - def __init__(self, referer=None, x_saasus_referer=None, *args, **kwargs): + def __init__(self, referer=None, x_saasus_referer=None, x_saasus_trace_id=None, *args, **kwargs): self.client = Client() self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id self.base_url = os.getenv("SAASUS_BASE_URL", "https://api.saasus.io/v1") super().__init__(*args, **kwargs) diff --git a/saasus_sdk_python/client/awsmarketplace_client.py b/saasus_sdk_python/client/awsmarketplace_client.py index dec07e8..490f72e 100644 --- a/saasus_sdk_python/client/awsmarketplace_client.py +++ b/saasus_sdk_python/client/awsmarketplace_client.py @@ -6,12 +6,13 @@ class SignedAwsmarketplaceApiClient(ApiClient): - def __init__(self, referer=None, x_saasus_referer=None, *args, **kwargs): + def __init__(self, referer=None, x_saasus_referer=None, x_saasus_trace_id=None, *args, **kwargs): super().__init__(*args, **kwargs) self.client = Client() self.configuration.default_headers = {} self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id self.base_url = os.getenv("SAASUS_BASE_URL", "https://api.saasus.io/v1") def call_api(self, resource_path, method, diff --git a/saasus_sdk_python/client/billing_client.py b/saasus_sdk_python/client/billing_client.py index 2a53344..1f38baf 100644 --- a/saasus_sdk_python/client/billing_client.py +++ b/saasus_sdk_python/client/billing_client.py @@ -6,12 +6,13 @@ class SignedBillingApiClient(ApiClient): - def __init__(self, referer=None, x_saasus_referer=None, *args, **kwargs): + def __init__(self, referer=None, x_saasus_referer=None, x_saasus_trace_id=None, *args, **kwargs): super().__init__(*args, **kwargs) self.client = Client() self.configuration.default_headers = {} self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id self.base_url = os.getenv("SAASUS_BASE_URL", "https://api.saasus.io/v1") def call_api(self, resource_path, method, diff --git a/saasus_sdk_python/client/client.py b/saasus_sdk_python/client/client.py index e0c2721..3577189 100644 --- a/saasus_sdk_python/client/client.py +++ b/saasus_sdk_python/client/client.py @@ -26,6 +26,7 @@ def __new__(cls): cls._instance = super().__new__(cls) cls._instance.referer = None cls._instance.x_saasus_referer = None + cls._instance.x_saasus_trace_id = None cls._instance.api_key = os.getenv("SAASUS_API_KEY", "") cls._instance.secret_key = os.getenv("SAASUS_SECRET_KEY", "") cls._instance.saas_id = os.getenv("SAASUS_SAAS_ID", "") @@ -55,4 +56,6 @@ def set_referer_header(self, header_params: dict) -> dict: header_params["Referer"] = self.referer if self.x_saasus_referer: header_params["X-SaaSus-Referer"] = self.x_saasus_referer + if self.x_saasus_trace_id: + header_params["X-SaaSus-Trace-Id"] = self.x_saasus_trace_id return header_params diff --git a/saasus_sdk_python/client/communication_client.py b/saasus_sdk_python/client/communication_client.py index a65bf59..c6eb42f 100644 --- a/saasus_sdk_python/client/communication_client.py +++ b/saasus_sdk_python/client/communication_client.py @@ -6,12 +6,13 @@ class SignedCommunicationApiClient(ApiClient): - def __init__(self, referer=None, x_saasus_referer=None, *args, **kwargs): + def __init__(self, referer=None, x_saasus_referer=None, x_saasus_trace_id=None, *args, **kwargs): super().__init__(*args, **kwargs) self.client = Client() self.configuration.default_headers = {} self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id self.base_url = os.getenv("SAASUS_BASE_URL", "https://api.saasus.io/v1") def call_api(self, resource_path, method, diff --git a/saasus_sdk_python/client/integration_client.py b/saasus_sdk_python/client/integration_client.py index 01e04b2..ac0de2e 100644 --- a/saasus_sdk_python/client/integration_client.py +++ b/saasus_sdk_python/client/integration_client.py @@ -6,12 +6,13 @@ class SignedIntegrationApiClient(ApiClient): - def __init__(self, referer=None, x_saasus_referer=None, *args, **kwargs): + def __init__(self, referer=None, x_saasus_referer=None, x_saasus_trace_id=None, *args, **kwargs): super().__init__(*args, **kwargs) self.client = Client() self.configuration.default_headers = {} self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id self.base_url = os.getenv("SAASUS_BASE_URL", "https://api.saasus.io/v1") def call_api(self, resource_path, method, diff --git a/saasus_sdk_python/client/pricing_client.py b/saasus_sdk_python/client/pricing_client.py index 2d89c62..d1af430 100644 --- a/saasus_sdk_python/client/pricing_client.py +++ b/saasus_sdk_python/client/pricing_client.py @@ -5,12 +5,13 @@ class SignedPricingApiClient(ApiClient): - def __init__(self, referer=None, x_saasus_referer=None, *args, **kwargs): + def __init__(self, referer=None, x_saasus_referer=None, x_saasus_trace_id=None, *args, **kwargs): super().__init__(*args, **kwargs) self.client = Client() self.configuration.default_headers = {} self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, diff --git a/saasus_sdk_python/middleware/middleware.py b/saasus_sdk_python/middleware/middleware.py index ab64861..8740b5d 100644 --- a/saasus_sdk_python/middleware/middleware.py +++ b/saasus_sdk_python/middleware/middleware.py @@ -26,12 +26,13 @@ def __init__(self): self.client = Client() self.base_url = os.getenv("SAASUS_BASE_URL", "https://api.saasus.io/v1") - def authenticate(self, id_token: str, referer: str | None = None, x_saasus_referer: str | None = None) -> tuple[None, AuthenticationError] | tuple[UserInfo, None] | tuple[None, ErrorResponse]: # noqa: E501 + def authenticate(self, id_token: str, referer: str | None = None, x_saasus_referer: str | None = None, x_saasus_trace_id: str | None = None) -> tuple[None, AuthenticationError] | tuple[UserInfo, None] | tuple[None, ErrorResponse]: # noqa: E501 if not id_token: return None, AuthenticationError("Invalid Authorization header") self.client.referer = referer self.client.x_saasus_referer = x_saasus_referer + self.client.x_saasus_trace_id = x_saasus_trace_id try: response = self.user_info(id_token) return response, None diff --git a/test/.DS_Store b/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a5a31a943eb1a7f7335151caf0e1267be2ba37c4 GIT binary patch literal 8196 zcmeHMzi$&U6n;*sHc}Ks)u9;}j)grt!x4oQRm#!{HA$-k$mK#vREeecCv@(g(5aPL znCOOJWM@H4t<<3sV(0UZOYAt8WPu>{S+c*A{hr^K?=1VCLqwuF+OH6miKu`o@nI3o zj3UQn^-9k4JOT>%6UEf-wk!2k9Q8eG?qCI20akz&U@T$GcdUB?afd0e6EtWIiaVR)7`w>k5dqTD?|97=1MR@#N=RfVzh&i?mBLDi<{B jiw~&Map3q5Lp%pCl|G@tL?e1o_(MR+zzr+#PZjtBa*-7J literal 0 HcmV?d00001