proxied

package
v7.6.77 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2024 License: GPL-3.0 Imports: 23 Imported by: 5

Documentation

Overview

This file focuses on a structure called ProxiedFlow. It's useful for us to run multiple roundtrippers in parallel and have a "preference" for one or more of them.

To breakdown this concept further, let's go with an example: Assume we want to run a request through our Lantern proxies (called the "chained roundtripper") **and** through domain fronting (called "fronted" roundtripper) where the fastest response is taken.

Let's also assume we want to have a preference for "chained roundtripper", meaning that if running a request through the "chained roundtripper" was the fastest roundtripper we've found (as opposed to the "fronted roundtripper" in this example), the **next** request you run will automatically go through "chained", and we wouldn't bother "fronted" roundtripper, unless it fails.

The code for this example will look like this:

    chainedRoundTripper, err := proxied.ChainedNonPersistent("")
    require.NoError(t, err)

    req, err := http.NewRequest("GET", "http://example.com", nil)
    require.NoError(t, err)
    flow := NewProxiedFlow(
    	&ProxiedFlowInput{
    		AddDebugHeaders: true,
    	},
    )

	   flow.
	     Add(proxied.FlowComponentID_Chained, chained, true).
      Add(proxied.FlowComponentID_Fronted, proxied.Fronted(masqueradeTimeout), false)
    resp, err := flow.RoundTrip(req)
    require.Error(t, err)

Package proxied provides http.Client implementations that use various combinations of chained and direct domain-fronted proxies.

Remember to call SetProxyAddr before obtaining an http.Client.

Index

Constants

View Source
const DefaultMasqueradeTimeout = 5 * time.Minute

Variables

View Source
var (

	// ErrChainedProxyUnavailable indicates that we weren't able to find a chained
	// proxy.
	ErrChainedProxyUnavailable = "chained proxy unavailable"
)

Functions

func AsRoundTripper

func AsRoundTripper(fn func(req *http.Request) (*http.Response, error)) http.RoundTripper

AsRoundTripper turns the given function into an http.RoundTripper.

func ChainedNonPersistent

func ChainedNonPersistent(rootCA string) (http.RoundTripper, error)

ChainedNonPersistent creates an http.RoundTripper that proxies through chained servers and does not use keepalive connections. If rootCA is specified, the RoundTripper will validate the server's certificate on TLS connections against that RootCA.

func ChainedPersistent

func ChainedPersistent(rootCA string) (http.RoundTripper, error)

ChainedPersistent creates an http.RoundTripper that uses keepalive connections persists and proxies through chained servers. If rootCA is specified, the RoundTripper will validate the server's certificate on TLS connections against that RootCA.

func DirectThenFrontedClient

func DirectThenFrontedClient(timeout time.Duration) *http.Client

DirectThenFrontedClient returns an http.Client that first attempts to connect directly to the origin and then falls back to using domain fronting. WARNING - if using this for non-idempotent requests like POST, you may see duplicate POSTS if the direct submission succeeds but fails to return a response by the timeout!

func Fronted

func Fronted(masqueradeTimeout time.Duration) http.RoundTripper

Fronted creates an http.RoundTripper that proxies request using domain fronting.

Leave masqueradeTimeout as 0 to use a default value.

func ParallelForIdempotent

func ParallelForIdempotent() http.RoundTripper

Uses ParallelPreferChained for idempotent requests (HEAD and GET) and ChainedThenFronted for all others.

func SetProxyAddr

func SetProxyAddr(addr eventual.Getter)

SetProxyAddr sets the eventual.Getter that's used to determine the proxy's address. This MUST be called before attempting to use the proxied package.

Types

type FlowComponentID

type FlowComponentID string
var (
	FlowComponentID_P2P     FlowComponentID = "p2p"
	FlowComponentID_Fronted FlowComponentID = "fronted"
	FlowComponentID_Chained FlowComponentID = "chained"
)

Enum of most used roundtrippers

func (FlowComponentID) String

func (id FlowComponentID) String() string

type OnCompleteRoundTrip

type OnCompleteRoundTrip func(FlowComponentID)

OnCompleteRoundTrip is called by the flow when it completes a roundtrip.

type OnStartRoundTrip

type OnStartRoundTrip func(FlowComponentID, *http.Request)

OnStartRoundTrip is called by the flow when it starts a new roundtrip.

type ProxiedFlow

type ProxiedFlow struct {
	// contains filtered or unexported fields
}

func NewProxiedFlow

func NewProxiedFlow(input *ProxiedFlowInput) *ProxiedFlow

NewProxiedFlow returns a new ProxiedFlow

func (*ProxiedFlow) Add

func (f *ProxiedFlow) Add(
	id FlowComponentID,
	rt http.RoundTripper,
	shouldPrefer bool,
) *ProxiedFlow

Add adds new roundtrippers to the flow. The highest priority components should be added first (i.e., 0 is the highest priority)

func (*ProxiedFlow) RoundTrip

func (f *ProxiedFlow) RoundTrip(
	originalReq *http.Request,
) (*http.Response, error)

RoundTrip makes ProxiedFlow implement the http.RoundTripper interface. This function works in two ways:

  • the "runner" code occurs in "f.runAllComponents()" and it's responsible for running all the roundtrippers in the flow (or just the preferred one, if one exists) and send the responses through "recvFlowRespCh"
  • the "reciever" code occurs in the "looper" block below and it's responsible for handling responses and errors

This function respects the request's original context

func (*ProxiedFlow) SetPreferredComponent

func (f *ProxiedFlow) SetPreferredComponent(id FlowComponentID) *ProxiedFlow

SetPreferredComponent sets the component with "id" as the preferred component. This function doesn't fail if the component doesn't exist.

Return *ProxiedFlow to chain function calls in a builder pattern.

type ProxiedFlowComponent

type ProxiedFlowComponent struct {
	http.RoundTripper
	// contains filtered or unexported fields
}

ProxiedFlowComponent is basically a wrapper around an http.RoundTripper that includes an ID and some additional flags

func (*ProxiedFlowComponent) Run

func (comp *ProxiedFlowComponent) Run(
	originalReq *http.Request,
	originalReqMu *sync.Mutex,
	onStartRoundTripFunc OnStartRoundTrip,
	onCompleteRoundTripFunc OnCompleteRoundTrip,
) *ProxiedFlowResponse

Run runs component "comp" by basically cloning the request and then roundtripping

type ProxiedFlowInput

type ProxiedFlowInput struct {
	// Can be set to true to add the value of
	// "roundTripperHeaderKey" to the response headers (not request). It's purely
	// used for assertions during unit tests.
	AddDebugHeaders bool
	// Runs when a flow component is about to start roundtripping
	OnStartRoundTripFunc OnStartRoundTrip
	// Runs when a flow component is is done roundtripping
	OnCompleteRoundTripFunc OnCompleteRoundTrip
}

ProxiedFlowInput is the input to NewProxiedFlow()

type ProxiedFlowResponse

type ProxiedFlowResponse struct {
	// contains filtered or unexported fields
}

ProxiedFlowResponse is a wrapper around an http.Response and an error, both coming from ProxiedFlowComponent.RoundTrip()

type RoundTripper

type RoundTripper interface {
	http.RoundTripper

	// SetMasqueradeTimeout specifies how long we're willing to wait for a valid
	// fronting masquerade before failing.
	SetMasqueradeTimeout(time.Duration)
}

RoundTripper implements http.RoundTripper and allows configuration of the masquerade timeout.

func ChainedThenFronted

func ChainedThenFronted() RoundTripper

ChainedThenFronted creates a new http.RoundTripper that attempts to send requests first through a chained server and then falls back to using a direct fronted server if the chained route didn't work.

func ChainedThenFrontedWith

func ChainedThenFrontedWith(rootCA string) RoundTripper

ChainedThenFrontedWith creates a new http.RoundTripper that attempts to send requests first through a chained server and then falls back to using a direct fronted server if the chained route didn't work.

func ParallelPreferChained

func ParallelPreferChained() RoundTripper

ParallelPreferChained creates a new http.RoundTripper that attempts to send requests through both chained and direct fronted routes in parallel. Once a chained request succeeds, subsequent requests will only go through Chained servers unless and until a request fails, in which case we'll start trying fronted requests again.

func ParallelPreferChainedWith

func ParallelPreferChainedWith(rootCA string) RoundTripper

ParallelPreferChainedWith creates a new http.RoundTripper that attempts to send requests through both chained and direct fronted routes in parallel. Once a chained request succeeds, subsequent requests will only go through Chained servers unless and until a request fails, in which case we'll start trying fronted requests again.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL