123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- from __future__ import annotations
- from typing import Any
- from flask import current_app, request
- from flask_security import current_user
- import requests
- class InternalApi(object):
- """
- Simple wrapper around the requests lib, which we use to talk to
- our actual internal JSON Api via requests. It can only be used to perform
- requests on the same URL root as the current request.
- - We use this because it is cleaner than calling the API code directly.
- That would re-use the same request we are working on here, which
- works differently in some ways like content-type and authentication.
- The Flask/Werkzeug request is also immutable, so we could not adapt the
- request anyways.
- - Also, we implement auth token handling
- - Finally we have some logic to control which error codes we want to raise.
- """
- _log_prefix = "Internal API call ― "
- def _auth_headers(self):
- return {
- "content-type": "application/json",
- "Authorization": current_user.get_auth_token(),
- }
- def _maybe_raise(
- self, response: requests.Response, do_not_raise_for: list | None = None
- ):
- """
- Raise an error in the API (4xx, 5xx) if the error code is not in the list of codes
- we want to ignore / handle explicitly.
- """
- if do_not_raise_for is None:
- do_not_raise_for = []
- if response.status_code not in do_not_raise_for:
- response.raise_for_status()
- def _url_root(self) -> str:
- """
- Get the root for the URLs this API should use to call FlexMeasures.
- """
- url_root = request.url_root
- if current_app.config.get("FLEXMEASURES_FORCE_HTTPS", False):
- # this replacement is for the case we are behind a load balancer who talks http internally
- url_root = url_root.replace("http://", "https://")
- return url_root
- def get(
- self,
- url: str,
- query: dict[str, Any] | None = None,
- do_not_raise_for: list | None = None,
- ) -> requests.Response:
- full_url = f"{self._url_root()}{url}"
- current_app.logger.debug(
- f"{self._log_prefix} Calling GET to {full_url} with query {query} ..."
- )
- response = requests.get(
- full_url,
- params=query,
- headers=self._auth_headers(),
- )
- self._maybe_raise(response, do_not_raise_for)
- return response
- def post(
- self,
- url: str,
- args: dict | None = None,
- do_not_raise_for: list | None = None,
- ) -> requests.Response:
- full_url = f"{self._url_root()}{url}"
- current_app.logger.debug(
- f"{self._log_prefix} Call POST to {full_url} with json data {args} ..."
- )
- response = requests.post(
- full_url,
- headers=self._auth_headers(),
- json=args if args else {},
- )
- self._maybe_raise(response, do_not_raise_for)
- return response
- def patch(
- self,
- url: str,
- args: dict | None = None,
- do_not_raise_for: list | None = None,
- ) -> requests.Response:
- full_url = f"{self._url_root()}{url}"
- current_app.logger.debug(
- f"{self._log_prefix} Calling PATCH to {full_url} with json data {args} ..."
- )
- response = requests.patch(
- full_url,
- headers=self._auth_headers(),
- json=args if args else {},
- )
- self._maybe_raise(response, do_not_raise_for)
- return response
- def delete(
- self,
- url: str,
- do_not_raise_for: list | None = None,
- ) -> requests.Response:
- full_url = f"{self._url_root()}{url}"
- current_app.logger.debug(f"{self._log_prefix} Calling DELETE to {full_url} ...")
- response = requests.delete(
- full_url,
- headers=self._auth_headers(),
- )
- self._maybe_raise(response, do_not_raise_for)
- return response
|