basyx commited on
Commit
4dcba1b
·
verified ·
1 Parent(s): 8b6e59b

fix: load diarization backend configuration safely

Browse files
Files changed (1) hide show
  1. app/services/diarization_service.py +46 -13
app/services/diarization_service.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
 
3
  import json
4
  import math
 
5
  from pathlib import Path
6
  from typing import Any
7
 
@@ -19,9 +20,13 @@ class DiarizationService:
19
  def __init__(self, settings: Settings) -> None:
20
  self.settings = settings
21
 
 
 
 
 
22
  @property
23
  def is_configured(self) -> bool:
24
- return bool(self.settings.diarization_url.strip())
25
 
26
  async def diarize(self, path: Path, mime_type: str, filename: str) -> list[dict[str, Any]]:
27
  if not self.is_configured:
@@ -35,33 +40,35 @@ class DiarizationService:
35
  size = path.stat().st_size
36
  except OSError as exc:
37
  raise ProcessingError("Unable to inspect diarization input") from exc
38
- if size > self.settings.diarization_max_input_bytes:
 
 
39
  raise InputError("Diarization input exceeds the configured size limit")
40
 
41
  headers = {
42
  "Content-Type": mime_type or "application/octet-stream",
43
  "X-Filename": filename[:255],
44
  }
45
- token = (
46
- self.settings.diarization_api_key.get_secret_value()
47
- if self.settings.diarization_api_key
48
- else ""
49
- )
50
  if token:
51
  headers["Authorization"] = f"Bearer {token}"
52
 
 
 
 
 
53
  timeout = httpx.Timeout(
54
- connect=self.settings.diarization_connect_timeout_seconds,
55
- read=self.settings.diarization_timeout_seconds,
56
- write=self.settings.diarization_timeout_seconds,
57
- pool=self.settings.diarization_connect_timeout_seconds,
58
  )
59
 
60
  try:
61
  async with httpx.AsyncClient(timeout=timeout, follow_redirects=False) as client:
62
  with path.open("rb") as handle:
63
  response = await client.post(
64
- self.settings.diarization_url.strip(),
65
  content=handle,
66
  headers=headers,
67
  )
@@ -72,7 +79,7 @@ class DiarizationService:
72
  raise ProcessingError(
73
  f"Diarization backend returned HTTP {response.status_code}"
74
  )
75
- if len(response.content) > self.settings.diarization_max_response_bytes:
76
  raise ProcessingError("Diarization backend response exceeds the configured limit")
77
 
78
  try:
@@ -102,3 +109,29 @@ class DiarizationService:
102
  normalized.append(span.model_dump())
103
 
104
  return normalized
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  import json
4
  import math
5
+ import os
6
  from pathlib import Path
7
  from typing import Any
8
 
 
20
  def __init__(self, settings: Settings) -> None:
21
  self.settings = settings
22
 
23
+ @property
24
+ def url(self) -> str:
25
+ return os.getenv("DIARIZATION_URL", "").strip()
26
+
27
  @property
28
  def is_configured(self) -> bool:
29
+ return bool(self.url)
30
 
31
  async def diarize(self, path: Path, mime_type: str, filename: str) -> list[dict[str, Any]]:
32
  if not self.is_configured:
 
40
  size = path.stat().st_size
41
  except OSError as exc:
42
  raise ProcessingError("Unable to inspect diarization input") from exc
43
+
44
+ max_input = self._int_env("DIARIZATION_MAX_INPUT_BYTES", 1_073_741_824, 1_048_576)
45
+ if size > max_input:
46
  raise InputError("Diarization input exceeds the configured size limit")
47
 
48
  headers = {
49
  "Content-Type": mime_type or "application/octet-stream",
50
  "X-Filename": filename[:255],
51
  }
52
+ token = os.getenv("DIARIZATION_API_KEY", "").strip()
 
 
 
 
53
  if token:
54
  headers["Authorization"] = f"Bearer {token}"
55
 
56
+ connect_timeout = self._float_env("DIARIZATION_CONNECT_TIMEOUT_SECONDS", 10.0, 0.1)
57
+ timeout_seconds = self._float_env("DIARIZATION_TIMEOUT_SECONDS", 300.0, 1.0)
58
+ max_response = self._int_env("DIARIZATION_MAX_RESPONSE_BYTES", 1_048_576, 1024)
59
+
60
  timeout = httpx.Timeout(
61
+ connect=connect_timeout,
62
+ read=timeout_seconds,
63
+ write=timeout_seconds,
64
+ pool=connect_timeout,
65
  )
66
 
67
  try:
68
  async with httpx.AsyncClient(timeout=timeout, follow_redirects=False) as client:
69
  with path.open("rb") as handle:
70
  response = await client.post(
71
+ self.url,
72
  content=handle,
73
  headers=headers,
74
  )
 
79
  raise ProcessingError(
80
  f"Diarization backend returned HTTP {response.status_code}"
81
  )
82
+ if len(response.content) > max_response:
83
  raise ProcessingError("Diarization backend response exceeds the configured limit")
84
 
85
  try:
 
109
  normalized.append(span.model_dump())
110
 
111
  return normalized
112
+
113
+ @staticmethod
114
+ def _int_env(name: str, default: int, minimum: int) -> int:
115
+ raw = os.getenv(name, "")
116
+ if not raw:
117
+ return default
118
+ try:
119
+ value = int(raw)
120
+ except ValueError as exc:
121
+ raise ProcessingError(f"{name} must be an integer") from exc
122
+ if value < minimum:
123
+ raise ProcessingError(f"{name} is below its minimum allowed value")
124
+ return value
125
+
126
+ @staticmethod
127
+ def _float_env(name: str, default: float, minimum: float) -> float:
128
+ raw = os.getenv(name, "")
129
+ if not raw:
130
+ return default
131
+ try:
132
+ value = float(raw)
133
+ except ValueError as exc:
134
+ raise ProcessingError(f"{name} must be a number") from exc
135
+ if not math.isfinite(value) or value < minimum:
136
+ raise ProcessingError(f"{name} is below its minimum allowed value")
137
+ return value