squid-forward-proxy

Squid Forward Proxy

Channel Revision Published Runs on
latest/edge 36 13 Feb 2026
Ubuntu 24.04
juju deploy squid-forward-proxy --channel edge
Show information

Platform:

Ubuntu
24.04

charms.squid_forward_proxy.v0.http_proxy

Library to manage the http-proxy relation.

This library contains the Requirer and Provider classes for handling the http-proxy interface.

Getting Started

To get started using the library, you just need to fetch the library using charmcraft.

cd some-charm
charmcraft fetch-lib charms.http_proxy.v0.http_proxy
Using library as a requirer

In the metadata.yaml of the charm, add the following:

requires:
  http-proxy:
    interface: http-proxy
    limit: 1

There are three ways to initialize the requirer class. For requirers that need to issue only a single request, they must either use the HttpProxyRequirer class or the HttpProxyDynamicRequirer class. HttpProxyRequirer class is used when the requirer parameters are known at initialization time. HttpProxyDynamicRequirer class is used when the requirer parameters are not known at initialization time and will be provided later through the request_http_proxy method. The main use case for the HttpProxyDynamicRequirer class is when the list of domains requiring proxy is dynamic. For requirers that need to issue multiple requests, they must use the HttpProxyPolyRequirer class.

  1. To initialize the requirer with parameters using the HttpProxyRequirer class:
from charms.http_proxy.v0.http_proxy import {
    HTTPProxyNotAvailableError,
    HttpProxyRequirer
    DEFAULT_HTTP_PROXY_INTEGRATION_NAME
)

class FooCharm(ops.CharmBase):
    def __init__(self, *args):
        ...
         self.http_proxy_requirer = HttpProxyRequirer(
            self,
             relation_name=DEFAULT_HTTP_PROXY_INTEGRATION_NAME,
            domains=["example.com", "example.org"],
            auth=["userpass", "none", "srcip", "srcip+userpass"],
            src_ips=[],
        )
        self.framework.observe(
            self.on[DEFAULT_HTTP_PROXY_INTEGRATION_NAME].relation_changed, self.get_proxies
        )
        self.framework.observe(self.on.secret_changed, self.get_proxies)

    def get_proxies(self, _: ops.EventBase):
        try:
            proxies = self.http_proxy_requirer.fetch_proxies()
        except HTTPProxyUnavailableError as e:
            logging.error(f"HTTP proxy not available. Proxy status: {e.status}")
            return None
        return (proxies.http_proxy, proxies.https_proxy)
  1. To initialize the requirer with no parameters using the HttpProxyDynamicRequirer class:
# This will simply initialize the requirer class and it won't perform any action.
# Later provide the requirer data through the request_http_proxy method.

from charms.http_proxy.v0.http_proxy import {
    HTTPProxyNotAvailableError,
    HttpProxyDynamicRequirer,
    DEFAULT_HTTP_PROXY_INTEGRATION_NAME
)

class FooCharmDynamic(ops.CharmBase):
    def __init__(self, *args):
        ...
        self.http_proxy_dynamic_requirer = HttpProxyDynamicRequirer(
            self,
            relation_name=DEFAULT_HTTP_PROXY_INTEGRATION_NAME,
        )
        self.framework.observe(
            self.on[DEFAULT_HTTP_PROXY_INTEGRATION_NAME].relation_changed, self.get_proxies
        )
        self.framework.observe(self.on.config_changed, self.provide_proxy)
        ...

    def provide_proxy(self, _: ops.EventBase):
        # If you have initialized the HttpProxyDynamicRequirer class
        # you can call the request_http_proxy method anywhere in your charm
        # to request proxy.
        if not self.model.unit.is_leader():
            return
        self.http_proxy_dynamic_requirer.request_http_proxy(
            domains=["example.com", "example.org"],
            auth=["userpass", "none", "srcip", "srcip+userpass"],
            src_ips=[],
        )

    def get_proxies(self, _: ops.EventBase):
        try:
            proxies = self.http_proxy_requirer.fetch_proxies()
        except HTTPProxyUnavailableError as e:
            logging.error(f"HTTP proxy not available. Proxy status: {e.status}")
            return None
        return (proxies.http_proxy, proxies.https_proxy)
  1. To initialize the requirer with multiple requests using the HttpProxyPolyRequirer class, refer to the implementation in http-proxy-policy-operator. This class is for more advanced use cases where developers want to issue multiple requests with different parameters.
Using library as a provider

In the metadata.yaml of the charm, add the following:

provides:
  http-proxy:
    interface: http-proxy

Import HTTPProxyPolyProvider in your charm by adding the following to src/charm.py:

from charms.http_proxy.v0.http_proxy import (
    DEFAULT_HTTP_PROXY_INTEGRATION_NAME,
    HttpProxyPolyProvider,
)

The provider class must be instantiated as follows:

class FooCharm:
    def __init__(self, *args):
        super().__init__(*args, **kwargs)
        ...
        self._http_proxy_provider = HttpProxyPolyProvider(self)
        # This will simply initialize the requirer class and it won't perform any action.
        self.framework.observe(
            self.on[DEFAULT_HTTP_PROXY_INTEGRATION_NAME].relation_changed, self.provide_proxy
        )
        ...

    def provide_proxy(self, event: ops.EventBase) -> None:
        if not self.model.unit.is_leader():
            return
        relation = self.model.get_relation(DEFAULT_HTTP_PROXY_INTEGRATION_NAME)
        proxy_requests = self._http_proxy_provider.open_request_list(relation.id)
        responses = self._http_proxy_provider.open_response_list(relation.id)
        for requirer in proxy_requests.get_requirer_ids():
            request = proxy_requests.get(requirer)
            responses.add_or_replace(
                requirer_id=request.id,
                status=http_proxy.PROXY_STATUS_READY,
                auth=request.auth[0],
                http_proxy="http://proxy.test",
                https_proxy="https://proxy.test",
                user=None,
            )

class ProxyConfig

Proxy configuration.

Attributes

http_proxy
HTTP proxy.
https_proxy
HTTPS proxy.

class HTTPProxyUnavailableError

Description

Raised when HTTP proxy is not available. None

Methods

HTTPProxyUnavailableError. __init__( self , message: str , status )

Initialize the exception.

Arguments

message

The exception message.

status

The HTTP proxy status.

def dedup(input_list)

Deduplicate a list without changing the order.

Arguments

input_list

The input list.

Returns

The deduplicated list.

class HttpProxySpec

HTTP proxy model.

Attributes

group
group id. Along with id, uniquely identifies the proxy request within a charm scope.
id
id. Along with group, uniquely identifies the proxy request within a charm scope.
domains
HTTP proxy destination domains.
auth
HTTP proxy authentication methods.
src_ips
HTTP proxy source IPs.

Methods

HttpProxySpec. parse_domain( domain: str )

Parse a domain string in the form of host[:port].

Arguments

domain

The domain string.

Returns

A (host, port) tuple. Port is 0 if not specified.

class HttpProxyRequest

HTTP proxy request model.

Attributes

implicit_src_ips
src_ips is provided implicitly.

class HttpProxyUser

HTTP proxy user model.

Attributes

username
username.
password
password.

Methods

HttpProxyUser. dump( self )

Dump the model with secret revealed.

Returns

Dictionary representation of the model with secret revealed.

class HttpProxyResponse

HTTP proxy response model.

Attributes

model_config
pydantic model config.
group
group id. Along with id, uniquely identifies the proxy request within a charm scope.
id
id. Along with group, uniquely identifies the proxy request within a charm scope.
status
HTTP proxy status.
auth
HTTP proxy authentication method.
http_proxy
HTTP proxy.
https_proxy
HTTPS proxy.
user
HTTP proxy user.

Methods

class IntegrationDataError

Description

Integration contains ill-formed data. None

class HttpProxyPolyProvider

Description

HTTP proxy provider. None

Methods

HttpProxyPolyProvider. __init__( self , charm , integration_name: str )

Initialize the object.

Arguments

charm

the charm instance.

integration_name

HTTP proxy integration name.

HttpProxyPolyProvider. open_request_list( self , integration_id: int )

Start reading the request list in the integration data.

Arguments

integration_id

integration id.

Returns

A instance of HttpProxyRequestListReader.

HttpProxyPolyProvider. open_response_list( self , integration_id: int )

Start reading/writing the response list in the integration data.

Arguments

integration_id

integration id.

Returns

A instance of HttpProxyResponseListReadWriter.

class HttpProxyPolyRequirer

Description

HTTP proxy requirer. None

Methods

HttpProxyPolyRequirer. __init__( self , charm , integration_name: str )

Initialize the object.

Arguments

charm

the charm instance.

integration_name

HTTP proxy integration name.

HttpProxyPolyRequirer. open_request_list( self , integration_id: int )

Start reading/writing the request list in the integration data.

Arguments

integration_id

integration id.

Returns

A instance of HttpProxyRequestListReadWriter.

HttpProxyPolyRequirer. open_response_list( self , integration_id: int )

Start reading the response list in the integration data.

Arguments

integration_id

integration id.

Returns

A instance of HttpProxyResponseListReader.

class HttpProxyRequirer

Description

HTTP proxy static requirer. None

Methods

HttpProxyRequirer. __init__( self , charm , relation_name: str )

Initialize the HttpProxyRequirer class.

Arguments

charm

The charm instance.

relation_name

The name of the relation to use for the HTTP proxy.

domains

Sequence of domains to request proxy access for.

auth

Sequence of authentication modes supported by the application. See AUTH_METHODS for valid values.

src_ips

Sequence of source IPs to override the source IP addresses provided by the Juju integration binding information.

class HttpProxyDynamicRequirer

Description

HTTP proxy dynamic requirer. None

Methods

HttpProxyDynamicRequirer. request_http_proxy( self , domains , auth , src_ips )

Request a HTTP proxy.

Arguments

domains

Sequence of domains to request proxy access for.

auth

Sequence of authentication modes supported by the application. See AUTH_METHODS for valid values.

src_ips

Sequence of source IPs to override the source IP addresses provided by the Juju integration binding information.