259 lines
9.2 KiB
Python
Executable File
259 lines
9.2 KiB
Python
Executable File
# Licensed to the Software Freedom Conservancy (SFC) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The SFC 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 base64
|
|
import os
|
|
import socket
|
|
from typing import Optional
|
|
from urllib import parse
|
|
|
|
import certifi
|
|
|
|
from selenium.webdriver.common.proxy import Proxy
|
|
from selenium.webdriver.common.proxy import ProxyType
|
|
|
|
|
|
class ClientConfig:
|
|
def __init__(
|
|
self,
|
|
remote_server_addr: str,
|
|
keep_alive: Optional[bool] = True,
|
|
proxy: Optional[Proxy] = Proxy(raw={"proxyType": ProxyType.SYSTEM}),
|
|
ignore_certificates: Optional[bool] = False,
|
|
init_args_for_pool_manager: Optional[dict] = None,
|
|
timeout: Optional[int] = None,
|
|
ca_certs: Optional[str] = None,
|
|
username: Optional[str] = None,
|
|
password: Optional[str] = None,
|
|
auth_type: Optional[str] = "Basic",
|
|
token: Optional[str] = None,
|
|
) -> None:
|
|
self.remote_server_addr = remote_server_addr
|
|
self.keep_alive = keep_alive
|
|
self.proxy = proxy
|
|
self.ignore_certificates = ignore_certificates
|
|
self.init_args_for_pool_manager = init_args_for_pool_manager or {}
|
|
self.timeout = timeout
|
|
self.username = username
|
|
self.password = password
|
|
self.auth_type = auth_type
|
|
self.token = token
|
|
|
|
self.timeout = (
|
|
(
|
|
float(os.getenv("GLOBAL_DEFAULT_TIMEOUT", str(socket.getdefaulttimeout())))
|
|
if os.getenv("GLOBAL_DEFAULT_TIMEOUT") is not None
|
|
else socket.getdefaulttimeout()
|
|
)
|
|
if timeout is None
|
|
else timeout
|
|
)
|
|
|
|
self.ca_certs = (
|
|
(os.getenv("REQUESTS_CA_BUNDLE") if "REQUESTS_CA_BUNDLE" in os.environ else certifi.where())
|
|
if ca_certs is None
|
|
else ca_certs
|
|
)
|
|
|
|
@property
|
|
def remote_server_addr(self) -> str:
|
|
""":Returns: The address of the remote server."""
|
|
return self._remote_server_addr
|
|
|
|
@remote_server_addr.setter
|
|
def remote_server_addr(self, value: str) -> None:
|
|
"""Provides the address of the remote server."""
|
|
self._remote_server_addr = value
|
|
|
|
@property
|
|
def keep_alive(self) -> bool:
|
|
""":Returns: The keep alive value."""
|
|
return self._keep_alive
|
|
|
|
@keep_alive.setter
|
|
def keep_alive(self, value: bool) -> None:
|
|
"""Toggles the keep alive value.
|
|
|
|
:Args:
|
|
- value: whether to keep the http connection alive
|
|
"""
|
|
self._keep_alive = value
|
|
|
|
@property
|
|
def proxy(self) -> Proxy:
|
|
""":Returns: The proxy used for communicating to the driver/server."""
|
|
return self._proxy
|
|
|
|
@proxy.setter
|
|
def proxy(self, proxy: Proxy) -> None:
|
|
"""Provides the information for communicating with the driver or
|
|
server.
|
|
For example: Proxy(raw={"proxyType": ProxyType.SYSTEM})
|
|
|
|
:Args:
|
|
- value: the proxy information to use to communicate with the driver or server
|
|
"""
|
|
self._proxy = proxy
|
|
|
|
@property
|
|
def ignore_certificates(self) -> bool:
|
|
""":Returns: The ignore certificate check value."""
|
|
return self._ignore_certificates
|
|
|
|
@ignore_certificates.setter
|
|
def ignore_certificates(self, ignore_certificates: bool) -> None:
|
|
"""Toggles the ignore certificate check.
|
|
|
|
:Args:
|
|
- value: value of ignore certificate check
|
|
"""
|
|
self._ignore_certificates = ignore_certificates
|
|
|
|
@property
|
|
def init_args_for_pool_manager(self) -> dict:
|
|
""":Returns: The dictionary of arguments will be appended while
|
|
initializing the pool manager."""
|
|
return self._init_args_for_pool_manager
|
|
|
|
@init_args_for_pool_manager.setter
|
|
def init_args_for_pool_manager(self, init_args_for_pool_manager: dict) -> None:
|
|
"""Provides dictionary of arguments will be appended while initializing the pool manager.
|
|
For example: {"init_args_for_pool_manager": {"retries": 3, "block": True}}
|
|
|
|
:Args:
|
|
- value: the dictionary of arguments will be appended while initializing the pool manager
|
|
"""
|
|
self._init_args_for_pool_manager = init_args_for_pool_manager
|
|
|
|
@property
|
|
def timeout(self) -> int:
|
|
""":Returns: The timeout (in seconds) used for communicating to the
|
|
driver/server."""
|
|
return self._timeout
|
|
|
|
@timeout.setter
|
|
def timeout(self, timeout: int) -> None:
|
|
"""Provides the timeout (in seconds) for communicating with the driver
|
|
or server.
|
|
|
|
:Args:
|
|
- value: the timeout (in seconds) to use to communicate with the driver or server
|
|
"""
|
|
self._timeout = timeout
|
|
|
|
def reset_timeout(self) -> None:
|
|
"""Resets the timeout to the default value of socket."""
|
|
self._timeout = socket.getdefaulttimeout()
|
|
|
|
@property
|
|
def ca_certs(self) -> str:
|
|
""":Returns: The path to bundle of CA certificates."""
|
|
return self._ca_certs
|
|
|
|
@ca_certs.setter
|
|
def ca_certs(self, ca_certs: str) -> None:
|
|
"""Provides the path to bundle of CA certificates for establishing
|
|
secure connections.
|
|
|
|
:Args:
|
|
- value: the path to bundle of CA certificates for establishing secure connections
|
|
"""
|
|
self._ca_certs = ca_certs
|
|
|
|
@property
|
|
def username(self) -> str:
|
|
"""Returns the username used for basic authentication to the remote
|
|
server."""
|
|
return self._username
|
|
|
|
@username.setter
|
|
def username(self, value: str) -> None:
|
|
"""Sets the username used for basic authentication to the remote
|
|
server."""
|
|
self._username = value
|
|
|
|
@property
|
|
def password(self) -> str:
|
|
"""Returns the password used for basic authentication to the remote
|
|
server."""
|
|
return self._password
|
|
|
|
@password.setter
|
|
def password(self, value: str) -> None:
|
|
"""Sets the password used for basic authentication to the remote
|
|
server."""
|
|
self._password = value
|
|
|
|
@property
|
|
def auth_type(self) -> str:
|
|
"""Returns the type of authentication to the remote server."""
|
|
return self._auth_type
|
|
|
|
@auth_type.setter
|
|
def auth_type(self, value: str) -> None:
|
|
"""Sets the type of authentication to the remote server if it is not
|
|
using basic with username and password."""
|
|
self._auth_type = value
|
|
|
|
@property
|
|
def token(self) -> str:
|
|
"""Returns the token used for authentication to the remote server."""
|
|
return self._token
|
|
|
|
@token.setter
|
|
def token(self, value: str) -> None:
|
|
"""Sets the token used for authentication to the remote server if
|
|
auth_type is not basic."""
|
|
self._token = value
|
|
|
|
def get_proxy_url(self) -> Optional[str]:
|
|
"""Returns the proxy URL to use for the connection."""
|
|
proxy_type = self.proxy.proxy_type
|
|
remote_add = parse.urlparse(self.remote_server_addr)
|
|
if proxy_type is ProxyType.DIRECT:
|
|
return None
|
|
if proxy_type is ProxyType.SYSTEM:
|
|
_no_proxy = os.environ.get("no_proxy", os.environ.get("NO_PROXY"))
|
|
if _no_proxy:
|
|
for entry in map(str.strip, _no_proxy.split(",")):
|
|
if entry == "*":
|
|
return None
|
|
n_url = parse.urlparse(entry)
|
|
if n_url.netloc and remote_add.netloc == n_url.netloc:
|
|
return None
|
|
if n_url.path in remote_add.netloc:
|
|
return None
|
|
return os.environ.get(
|
|
"https_proxy" if self.remote_server_addr.startswith("https://") else "http_proxy",
|
|
os.environ.get("HTTPS_PROXY" if self.remote_server_addr.startswith("https://") else "HTTP_PROXY"),
|
|
)
|
|
if proxy_type is ProxyType.MANUAL:
|
|
return self.proxy.sslProxy if self.remote_server_addr.startswith("https://") else self.proxy.http_proxy
|
|
return None
|
|
|
|
def get_auth_header(self) -> Optional[dict]:
|
|
"""Returns the authorization to add to the request headers."""
|
|
auth_type = self.auth_type.lower()
|
|
if auth_type == "basic" and self.username and self.password:
|
|
credentials = f"{self.username}:{self.password}"
|
|
encoded_credentials = base64.b64encode(credentials.encode("utf-8")).decode("utf-8")
|
|
return {"Authorization": f"Basic {encoded_credentials}"}
|
|
if auth_type == "bearer" and self.token:
|
|
return {"Authorization": f"Bearer {self.token}"}
|
|
if auth_type == "oauth" and self.token:
|
|
return {"Authorization": f"OAuth {self.token}"}
|
|
return None
|