| 125 | |
| 126 | |
| 127 | class _BedrockSigV4Auth: |
| 128 | def __init__( |
| 129 | self, |
| 130 | *, |
| 131 | config: BedrockAwsAuthConfig, |
| 132 | base_url: httpx.URL, |
| 133 | auth: BedrockAwsAuth | None = None, |
| 134 | ) -> None: |
| 135 | self._config = config |
| 136 | self._base_url = base_url |
| 137 | self._auth = auth |
| 138 | |
| 139 | def _validate_request(self, request: httpx.Request) -> bytes: |
| 140 | _assert_provider_owns_authorization(request) |
| 141 | if not _same_origin(request.url, self._base_url): |
| 142 | raise OpenAIError( |
| 143 | "Refusing to sign a Bedrock request for an origin other than the configured provider URL." |
| 144 | ) |
| 145 | |
| 146 | endpoint_region_match = _CANONICAL_BEDROCK_HOST.fullmatch(request.url.host) |
| 147 | if endpoint_region_match is not None and endpoint_region_match.group(1) != self._config.region: |
| 148 | raise OpenAIError( |
| 149 | f"The Bedrock endpoint region `{endpoint_region_match.group(1)}` does not match the " |
| 150 | f"SigV4 region `{self._config.region}`." |
| 151 | ) |
| 152 | |
| 153 | return _body_for_signing(request) |
| 154 | |
| 155 | def _sign(self, request: httpx.Request, *, auth: BedrockAwsAuth, body: bytes) -> None: |
| 156 | for header in _AWS_SIGNING_HEADERS: |
| 157 | request.headers.pop(header, None) |
| 158 | |
| 159 | signed_headers = auth.sign( |
| 160 | method=request.method, |
| 161 | url=str(request.url), |
| 162 | headers=dict(request.headers), |
| 163 | body=body, |
| 164 | ) |
| 165 | request.headers.clear() |
| 166 | request.headers.update(signed_headers) |
| 167 | |
| 168 | def prepare_request(self, request: httpx.Request) -> None: |
| 169 | body = self._validate_request(request) |
| 170 | if self._auth is None: |
| 171 | self._auth = BedrockAwsAuth(self._config) |
| 172 | self._sign(request, auth=self._auth, body=body) |
| 173 | |
| 174 | async def prepare_async_request(self, request: httpx.Request) -> None: |
| 175 | body = self._validate_request(request) |
| 176 | if self._auth is None: |
| 177 | self._auth = await asyncify(BedrockAwsAuth)(self._config) |
| 178 | |
| 179 | signed_headers = await asyncify(self._auth.sign)( |
| 180 | method=request.method, |
| 181 | url=str(request.url), |
| 182 | headers={ |
| 183 | name: value for name, value in request.headers.items() if name.lower() not in _AWS_SIGNING_HEADERS |
| 184 | }, |