blob: f0a801589617b5dc5a60ac298ca5be96135766cf [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import json
import traceback
import requests
from pyhugegraph.utils.exceptions import (
NotAuthorizedError,
NotFoundError,
ServiceUnavailableException,
)
from pyhugegraph.utils.log import log
def create_exception(response_content):
data = json.loads(response_content)
if "ServiceUnavailableException" in data["exception"]:
raise ServiceUnavailableException(
f'ServiceUnavailableException, "message": "{data["message"]}",'
f' "cause": "{data["cause"]}"'
)
raise Exception(response_content)
def check_if_authorized(response):
if response.status_code == 401:
raise NotAuthorizedError(
f"Please check your username and password. {str(response.content)}"
)
return True
def check_if_success(response, error=None):
if (not str(response.status_code).startswith("20")) and check_if_authorized(
response
):
if error is None:
error = NotFoundError(response.content)
req = response.request
req_body = req.body if req.body else "Empty body"
response_body = response.text if response.text else "Empty body"
# Log the detailed information
print(
f"\033[93mError-Client:\n"
f"Request URL: {req.url}, Request Body: {req_body}\nResponse Body: "
f"{response_body}\033[0m"
)
raise error
return True
class ResponseValidation:
def __init__(self, content_type: str = "json", strict: bool = True) -> None:
super().__init__()
self._content_type = content_type
self._strict = strict
def __call__(self, response: requests.Response, method: str, path: str):
"""
Validate the HTTP response according to the provided content type and strictness.
:param response: HTTP response object
:param method: HTTP method used (e.g., 'GET', 'POST')
:param path: URL path of the request
:return: Parsed response content or empty dict if none applicable
"""
result = {}
try:
response.raise_for_status()
if response.status_code == 204:
log.debug("No content returned (204) for %s: %s", method, path)
else:
if self._content_type == "raw":
result = response
elif self._content_type == "json":
result = response.json()
elif self._content_type == "text":
result = response.text
else:
raise ValueError(f"Unknown content type: {self._content_type}")
except requests.exceptions.HTTPError as e:
if not self._strict and response.status_code == 404:
log.info("Resource %s not found (404)", path)
else:
try:
details = response.json().get("exception", "key 'exception' not found")
except (ValueError, KeyError):
details = "key 'exception' not found"
req_body = response.request.body if response.request.body else "Empty body"
req_body = req_body.encode('utf-8').decode('unicode_escape')
log.error( # pylint: disable=logging-fstring-interpolation
f"{method}: {e}\n[Body]: {req_body}\n[Server Exception]: {details}"
)
if response.status_code == 404:
raise NotFoundError(response.content) from e
raise e
except Exception: # pylint: disable=broad-exception-caught
log.error( # pylint: disable=logging-fstring-interpolation
f"Unhandled exception occurred: {traceback.format_exc()}"
)
return result
def __repr__(self) -> str:
return f"ResponseValidation(content_type={self._content_type}, strict={self._strict})"