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
- Variables
- func AsRoundTripper(fn func(req *http.Request) (*http.Response, error)) http.RoundTripper
- func ChainedNonPersistent(rootCA string) (http.RoundTripper, error)
- func ChainedPersistent(rootCA string) (http.RoundTripper, error)
- func DirectThenFrontedClient(timeout time.Duration) *http.Client
- func Fronted(masqueradeTimeout time.Duration) http.RoundTripper
- func ParallelForIdempotent() http.RoundTripper
- func SetProxyAddr(addr eventual.Getter)
- type FlowComponentID
- type OnCompleteRoundTrip
- type OnStartRoundTrip
- type ProxiedFlow
- type ProxiedFlowComponent
- type ProxiedFlowInput
- type ProxiedFlowResponse
- type RoundTripper
Constants ¶
const DefaultMasqueradeTimeout = 5 * time.Minute
Variables ¶
var ( // proxy. ErrChainedProxyUnavailable = "chained proxy unavailable" )
Functions ¶
func AsRoundTripper ¶
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 ¶
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 ¶
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 ¶
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.