Proxy Settings

Tags: settings

Examples

Defaults

Here is an example with defaults, and some stub values for required or sequence-based settings:

proxy:
  endpoints:
  - controller: null
    description: null
    name: my-endpoint
    port: 4000
    remote:
      break_on:
      - network_error
      - unhandled_exception
      check_after: 10.0
      endpoints:
      - liveness:
          type: inherit
        pools:
        - default
        url: https://httpbin.org/
      liveness:
        type: inherit
      min_pool_size: 1
      probe:
        headers: {}
        interval: 10.0
        method: GET
        path: /
        timeout: 10.0
        verify: true

With multiple remote endpoints

Here is an example showing how to configure multiple remote endpoints:

proxy:
  endpoints:
    - # An identifier for this local endpoint, used to reference it in code, rules and
      # dashboard. Must be unique for a given harp instance.
      name: httpbins

      # a human-readable description of the endpoint (optional)
      description: A very informative description

      # the local listening port for this endpoint
      port: 4000

      # the controller to use for this endpoint, "null" means default but you can specify
      # a custom controller. Most of the time you will want to use the default controller
      # and thus do not include this line.
      controller: null

      # the remote to proxy to, which can be anything from a single url to a complex
      # multipool configuration with # defaults and fallbacks, healthcheck probes, etc.
      remote:
        # the minimum number of endpoints to try to keep in the active pool. If the number
        # of active endpoints falls below this number, the proxy will attempt to bring them
        # back up to this number by including endpoints from the fallback pool.
        min_pool_size: 2

        # Endpoints
        endpoints:
          - url: "https://api1.example.com/"
          - url: "https://api2.example.com/"
          - url: "https://fallback.example.com/"
            pools: [fallback]
            liveness:
              type: ignore

        # Liveness settings for all endpoints, if not overriden by a specific endpoint's
        # liveness.
        liveness:
          type: naive
          failure_threshold: 2
          success_threshold: 2

        # A periodic probe to try to close the circuit breaker even if it's not actively
        # queried by the end user.
        probe:
          method: GET
          path: /healthz
          timeout: 10.0

Reference

Implementation (python): ProxySettings

Title

Description

Type

Format

Required

Endpoints

endpoints

array[EndpointSettings]

Endpoints 0 Name

endpoints/0/name

string

Required

Endpoints 0 Port

endpoints/0/port

integer

Required

Endpoints 0 Description

endpoints/0/description

object

Endpoints 0 Controller

endpoints/0/controller

object

Endpoints 0 Remote

endpoints/0/remote

object

.endpoints[]

Implementation (python): EndpointSettings

Title

Description

Type

Format

Required

Name

name

string

Required

Port

port

integer

Required

Description

description

object

Controller

controller

object

Remote

remote

object

.endpoints[].remote

Implementation (python): RemoteSettings

Title

Description

Type

Format

Required

Min Pool Size

min_pool_size

integer

Default

1

Break On

break_on

array[string]

Default

- network_error
- unhandled_exception

Check After

check_after

number

Default

10.0

Endpoints

endpoints

array[RemoteEndpointSettings]

Endpoints 0 Url

endpoints/0/url

string

uri

Required

Endpoints 0 Pools

endpoints/0/pools

array[string]

Default

- default

Endpoints 0 Liveness

endpoints/0/liveness

object

Probe

probe

object

Liveness

liveness

object

Default

type: inherit

.endpoints[].remote.endpoint

Implementation (python): RemoteEndpointSettings

Title

Description

Type

Format

Required

Url

url

string

uri

Required

Pools

pools

array[string]

Default

- default

Liveness

liveness

object

.endpoints[].remote.probe

Implementation (python): RemoteProbeSettings

Title

Description

Type

Format

Required

Method

method

string

Default

GET

Path

path

string

Default

/

Headers

headers

object

Interval

interval

number

Default

10.0

Timeout

timeout

number

Default

10.0

Verify

verify

boolean

Default

true

…liveness

Can be set at the remote enpoint level or at the remote level. If all levels are set to inherit, will use a naive implementation by default.

Implementation (python): BaseLivenessSettings

Title

Description

Type

Format

Required

Type

type

string

Default

inherit

This is the base type, actual implementation will depend on choosen type, documented below in order of complexity.

Inherit

Implementation (python): InheritLivenessSettings

Title

Description

Type

Format

Required

Type

type

string

Default

inherit

Ignore

Implementation (python): IgnoreLivenessSettings

Title

Description

Type

Format

Required

Type

type

string

Required

Naive

Implementation (python): NaiveLivenessSettings

Title

Description

Type

Format

Required

Type

type

string

Required

Failure Threshold

failure_threshold

integer

Default

1

Success Threshold

success_threshold

integer

Default

1

Leaky Bucket

Implementation (python): LeakyBucketLivenessSettings

Title

Description

Type

Format

Required

Type

type

string

Required

Rate

rate

number

Default

1.0

Capacity

capacity

number

Default

60.0

Threshold

threshold

number

Default

10.0

Class Diagram

Todo

This should be completely autogenerated, for now it was made using pyreverse harp_apps.proxy.settings -o dot for inheritance, followed by a manual edition to add relations. We can use this base but then introspect pydantic models to make sure we have all the relations, amnual edit is error prone.

digraph "classes" { rankdir = TB charset = "utf-8" "harp_apps.proxy.settings.BaseProxySettings" [color = "black", fontcolor = "black", label = <{BaseProxySettings|<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.Proxy" [color = "black", fontcolor = "black", label = <{Proxy|endpoints<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.ProxySettings" [color = "black", fontcolor = "black", label = <{ProxySettings|endpoints : list[EndpointSettings]<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.ProxySettings" -> "harp_apps.proxy.settings.BaseProxySettings" [arrowhead = "empty", arrowtail = "none"]; "harp_apps.proxy.settings.endpoint.BaseEndpointSettings" [color = "black", fontcolor = "black", label = <{BaseEndpointSettings|description : Optional[str]<br ALIGN="LEFT"/>name : str<br ALIGN="LEFT"/>port : int<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.endpoint.Endpoint" [color = "black", fontcolor = "black", label = <{Endpoint|remote : Optional[Remote]<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.endpoint.EndpointSettings" [color = "black", fontcolor = "black", label = <{EndpointSettings|remote : Optional[RemoteSettings]<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.BaseRemoteSettings" [color = "black", fontcolor = "black", label = <{BaseRemoteSettings|break_on : list[str]<br ALIGN="LEFT"/>check_after : float<br ALIGN="LEFT"/>min_pool_size : int<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.Remote" [color = "black", fontcolor = "black", label = <{Remote|current_pool<br ALIGN="LEFT"/>current_pool_name : str<br ALIGN="LEFT"/>endpoints<br ALIGN="LEFT"/>probe : Optional[RemoteProbe]<br ALIGN="LEFT"/>|check()<br ALIGN="LEFT"/>check_forever()<br ALIGN="LEFT"/>get_url(): str<br ALIGN="LEFT"/>notify_url_status(url, status)<br ALIGN="LEFT"/>refresh()<br ALIGN="LEFT"/>set_checking(url)<br ALIGN="LEFT"/>set_down(url)<br ALIGN="LEFT"/>set_up(url)<br ALIGN="LEFT"/>}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.endpoint.RemoteEndpoint" [color = "black", fontcolor = "black", label = <{RemoteEndpoint|failure_reasons : Optional[set]<br ALIGN="LEFT"/>failure_score : int<br ALIGN="LEFT"/>status : int<br ALIGN="LEFT"/>success_score : int<br ALIGN="LEFT"/>|failure(reason: str)<br ALIGN="LEFT"/>success()<br ALIGN="LEFT"/>}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.endpoint.RemoteEndpointSettings" [color = "black", fontcolor = "black", label = <{RemoteEndpointSettings|failure_threshold : Annotated[int, Field(gt=0)]<br ALIGN="LEFT"/>pools : List[str]<br ALIGN="LEFT"/>success_threshold : Annotated[int, Field(gt=0)]<br ALIGN="LEFT"/>url : Annotated<br ALIGN="LEFT"/>|serialize_in_order(value: List[str])<br ALIGN="LEFT"/>validate_pools(pools: List[str]): List[str]<br ALIGN="LEFT"/>}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.probe.RemoteProbe" [color = "black", fontcolor = "black", label = <{RemoteProbe|<br ALIGN="LEFT"/>|async_client()<br ALIGN="LEFT"/>check(client: httpx.AsyncClient, endpoint: 'RemoteEndpoint')<br ALIGN="LEFT"/>}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.probe.RemoteProbeSettings" [color = "black", fontcolor = "black", label = <{RemoteProbeSettings|headers : dict<br ALIGN="LEFT"/>interval : float<br ALIGN="LEFT"/>method : str<br ALIGN="LEFT"/>path : str<br ALIGN="LEFT"/>timeout : float<br ALIGN="LEFT"/>verify : bool<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.RemoteSettings" [color = "black", fontcolor = "black", label = <{RemoteSettings|endpoints : Optional[list[RemoteEndpointSettings]]<br ALIGN="LEFT"/>probe : Optional[RemoteProbeSettings]<br ALIGN="LEFT"/>|}>, shape = "record", style = "solid"]; "harp_apps.proxy.settings.remote.RemoteSettings" -> "harp_apps.proxy.settings.remote.BaseRemoteSettings" [arrowhead = "empty", arrowtail = "none"]; "harp_apps.proxy.settings.endpoint.EndpointSettings" -> "harp_apps.proxy.settings.endpoint.BaseEndpointSettings" [arrowhead = "empty", arrowtail = "none"]; // settings tree "harp_apps.proxy.settings.ProxySettings" -> "harp_apps.proxy.settings.endpoint.EndpointSettings" [arrowhead = none, headlabel = "0..n"]; "harp_apps.proxy.settings.endpoint.EndpointSettings" -> "harp_apps.proxy.settings.remote.RemoteSettings" [arrowhead = none, headlabel = "0..1"]; "harp_apps.proxy.settings.remote.RemoteSettings" -> "harp_apps.proxy.settings.remote.probe.RemoteProbeSettings" [arrowhead = none, headlabel = "0..1"]; "harp_apps.proxy.settings.remote.RemoteSettings" -> "harp_apps.proxy.settings.remote.endpoint.RemoteEndpointSettings" [arrowhead = none, headlabel = "0..n"]; // statefuls tree "harp_apps.proxy.settings.Proxy" -> "harp_apps.proxy.settings.ProxySettings" [arrowhead = none, headlabel = "1"]; "harp_apps.proxy.settings.Proxy" -> "harp_apps.proxy.settings.endpoint.Endpoint" [arrowhead = none, headlabel = "0..n"]; "harp_apps.proxy.settings.endpoint.Endpoint" -> "harp_apps.proxy.settings.endpoint.EndpointSettings" [arrowhead = none, headlabel = "1"]; "harp_apps.proxy.settings.endpoint.Endpoint" -> "harp_apps.proxy.settings.remote.Remote" [arrowhead = none, headlabel = "0..1"]; "harp_apps.proxy.settings.remote.Remote" -> "harp_apps.proxy.settings.remote.RemoteSettings" [arrowhead = none, headlabel = "1"]; "harp_apps.proxy.settings.remote.Remote" -> "harp_apps.proxy.settings.remote.endpoint.RemoteEndpoint" [arrowhead = none, headlabel = "0..n"]; "harp_apps.proxy.settings.remote.Remote" -> "harp_apps.proxy.settings.remote.probe.RemoteProbe" [arrowhead = none, headlabel = "0..1"]; "harp_apps.proxy.settings.remote.endpoint.RemoteEndpoint" -> "harp_apps.proxy.settings.remote.endpoint.RemoteEndpointSettings" [arrowhead = none, headlabel = "1"]; "harp_apps.proxy.settings.remote.probe.RemoteProbe" -> "harp_apps.proxy.settings.remote.probe.RemoteProbeSettings" [arrowhead = none, headlabel = "1"]; }