gogetter

package module
v2.1.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2016 License: MIT Imports: 5 Imported by: 4

README

gogetter

Small Go library for wrapping http.Client's Get method.

Usage

Documentation is available via GoDoc.

Description

One of the strength's of Go's interface system is that it allows easy composability of functionality through interfaces. What happens if you want to slightly modify the behavior of http.Client's Get method? In Go you would create a composing function that has an identical API that can be inserted between http.Client and the code that requires this additional functionality.

Gogetter is a collection of small wrappers that can be composed to provide additional standard fucnctionality around the http.Client's Get method.

Supported Use Cases

While the objects in this library allow easy wrapping of http.Client, don't forget that you can customize the base http.Client instance for your application. For instance, the below example configures each http.Client instance to attempt to re-use connections with the Keep-Alive header, and provide a request timeout.

    // convert remote address to Getter
    func addr2getter(addr string) gogetter.Getter {
        return &http.Client{
            Timeout: time.Duration(timeout),
            Transport: &http.Transport{
                MaxIdleConnsPerHost: int(maxConns),
            },
        }
    }
Prefixer

Especially when using a round-robin collection of servers, the final URL used by http.Client's Get method must be modified by prefixing the URL with the address of the remote machine. That's where Prefixer becomes handy.

Recall that Getters wrap each other, and the base Getter is simply an http.Client instance, configured as your appliction requires.

    // convert remote address to Getter
    func addr2getter(addr string) gogetter.Getter {
        return &gogetter.Prefixer{
            Prefix: fmt.Sprintf("http://%s/some/resource/route?", addr),
            // NOTE: customize http.Client as desired:
            Getter: &http.Client{
                Timeout: time.Duration(timeout),
                Transport: &http.Transport{
                    MaxIdleConnsPerHost: int(maxConns),
                },
            },
        }
    }
RoundRobin

Perhaps you'd like your application to round-robin HTTP GET calls to a collection of different servers providing this interface when there is no actual load balancer configured. RoundRobin will send successive Get invocations to different underlying http.Client instances.

    func addrs2getter(addrs []string) (gogetter.Getter, error) {
        if len(hostnames) == 0 {
            return nil, fmt.Errorf("cannot create Getter without at least one server address")
        }

        var getter gogetter.Getter

        if len(hostnames) == 1 {
            getter = addr2getter(hostnames[0])
        } else {
            var hostGetters []gogetter.Getter
            for _, addr := range addrs {
                hostGetters = append(hostGetters, addr)
            }
            hg = gogetter.NewRoundRobin(hostGetters)
        }

        return getter, nil
    }
Retrier

Perhaps you'd like to conditionally retry failed HTTP GET calls for certain network or connection errors automatically. Normally your application would check the error type, and if the error type was temporary, it would re-issue the GET method. The Retrier allows your application to encode your retry business logic into a function, and this library will retry those errors for you.

    func addrs2getter() {
        // (as above)

        // set 'retryCount' to a positive number if you'd like to retry on errors; set it to 0 to
        // send queries only once
        retryCount := 10
        if retryCount > 0 {
            getter = &gogetter.Retrier{
                Getter:     getter,
                RetryCount: retryCount,
            }
        }

        return getter, nil
    }
Failer

This wrapper is designed for testing purposes to similate random failed http.Get invocations by returning an error. You would never use this in production code.

    ...

    getter = &Failure{Frequency: 0.9, Getter: getter}

    ...

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Failer

type Failer struct {
	Getter    Getter  // Getter's Get method is invoked when the Failer instance doesn't fail.
	Frequency float64 // Frequency specifies how often a failure should occur. Set to 0.0 to never fail and 1.0 to always fail.
}

Failer is used for testing by causing periodic Get failures.

WARNING: Don't use this in production code.

func (*Failer) Get

func (f *Failer) Get(url string) (*http.Response, error)

Get periodically responds to the Get method, and periodically fails.

type Getter

type Getter interface {
	Get(url string) (*http.Response, error)
}

Getter is the interface implemented by an object that provides a Get method identical to http.Client's method, to allow composition of functionality.

func NewRoundRobin added in v1.1.0

func NewRoundRobin(getters []Getter) Getter

NewRoundRobin returns a Getter that sends successive queries to all the Getters its list.

type Prefixer

type Prefixer struct {
	// The object whose Get method is invoked to get results for a query.
	Getter Getter

	// Prefix for each query, commonly the hostname.
	Prefix string
}

Prefixer prepends the specified prefix to the URL before redirecting to the underlying Getter.

func (*Prefixer) Get

func (p *Prefixer) Get(url string) (*http.Response, error)

Get prepends the specified prefix to the URL before redirecting to the underlying Getter.

type Retrier

type Retrier struct {
	// Getter is the object whose Get method is invoked to Get the results for a query.
	Getter Getter

	// RetryCount is number of query retries to be issued if query returns error. Leave 0 to
	// never retry query errors. But if you don't want to retry errors, It's best not to use a
	// Retrier...
	RetryCount int

	// RetryCallback is predicate function that tests whether query should be retried for a
	// given error. Leave nil to retry all errors.
	RetryCallback func(error) bool

	// RetryPause is the amount of time to wait before retrying the query with the underlying
	// Getter.
	RetryPause time.Duration
}

Retrier will optionally retry queries that fail.

WARNING: Retrier *should* wrap RoundRobin. That way retries don't go to the same dead server over and over.

func (*Retrier) Get

func (r *Retrier) Get(url string) (response *http.Response, err error)

Get attempts the specified query, and optionally retries a specified number of times, based on the results of calling the RetryCallback function.

Jump to

Keyboard shortcuts

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