Source code for pi_portal.modules.integrations.network.http

"""Network utilities for the Pi Portal Project."""

import logging
import shutil
from typing import Optional

import requests
import urllib3
from requests import Session
from requests.adapters import HTTPAdapter


[docs]class HttpClientError(Exception): """Raised when the HTTP client encounters an error."""
[docs]class HttpClient: """Remote HTTP server client. :param log: A logging instance. """ retry_config = urllib3.Retry(5, redirect=5) def __init__(self, log: logging.Logger) -> None: self.log = log
[docs] def get(self, url: str, target: Optional[str] = None) -> requests.Response: """Fetch a remote URL and save to a local file system target. :param url: The remote URL to fetch. :param target: The local path to write the content to. :returns: The http response object. """ self.log.info(f"HTTP GET: '{url}' ...") session = self._create_request_session() response = session.get(url, stream=True) if response.ok: self.log.info(f"HTTP GET: Connected to '{url}' ...") if target: self._save_response(response, target) return response self.log.error( "HTTP GET: Unable to retrieve remote file from '%s' !", url, ) raise HttpClientError(url)
def _create_request_session(self) -> Session: adapter = HTTPAdapter(max_retries=self.retry_config) session = Session() session.mount('http://', adapter) session.mount('https://', adapter) return session def _save_response(self, response: requests.Response, target: str) -> None: with open( target, 'wb', ) as out_file: response.raw.decode_content = True shutil.copyfileobj(response.raw, out_file) self.log.info(f"HTTP GET: Successfully saved '{target}' !")