train

package module
Version: v0.0.0-...-523ebca Latest Latest
Warning

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

Go to latest
Published: Apr 9, 2017 License: MIT Imports: 1 Imported by: 10

README

train

Chainable HTTP client middleware. Borrowed from OkHttp.

Interceptors monitor outgoing requests, and incoming responses. Here's an interceptor that logs all requests made and responses received by the client.

import "github.com/f2prateek/train"

f := func(chain train.Chain) (*http.Response, error) {
  req := chain.Request()
  fmt.Println(httputil.DumpRequestOut(req, false))

  resp, err := chain.Proceed(req)
  fmt.Println(httputil.DumpRequestOut(req, false))

  return resp, err
})

transport := train.Transport(train.InterceptorFunc(f))
client := &http.Client{
  Transport: transport,
}

client.Get("https://golang.org")

// Output:
// GET / HTTP/1.1
// Host: 127.0.0.1:64598
//
// HTTP/1.1 200 OK
// Content-Length: 13
// Content-Type: text/plain; charset=utf-8
// Date: Thu, 25 Feb 2016 09:49:28 GMT

Interceptors may modify requests and responses.

func Intercept(chain train.Chain) (*http.Response, error) {
  req := chain.Request()
  req.Header.Add("User-Agent", "Train Example")

  resp, err := chain.Proceed(req)
  resp.Header.Add("Cache-Control", "max-age=60")

  return resp, err
})

Or interceptors can simply short circuit the chain.

func Intercept(train.Chain) (*http.Response, error) {
  return cannedResponse, cannedError
})

Train chains interceptors so that they can be plugged into any http.Client. For example, this chain will transparently, retry requests for temporary errors, log requests/responses and increment some request/response stats.

import "github.com/f2prateek/log"
import "github.com/f2prateek/statsd"
import "github.com/f2prateek/hickson"
import "github.com/f2prateek/hickson/temporary"

errInterceptor := hickson.New(hickson.RetryMax(5, temporary.RetryErrors()))
logInterceptor := log.New(os.Stdout, log.Body)
statsInterceptor := statsd.New(statsdClient)

transport := train.Transport(errInterceptor, logInterceptor, statsInterceptor)
client := &http.Client{
  Transport: transport,
}

client.Get("https://golang.org")

Interceptors are consulted in the order they are provided. You'll need to decide what order you want your interceptors to be called in.

// This chain will:
// 1. Start monitoring errors.
// 2. Log the request.
// 3. Record stats about the request.
// 4. Do HTTP.
// 5. Record stats about the response.
// 6. Log the response.
// 7. Retry temporary errors, if any, and restart the chain at 2 in that case.
transport := train.Transport(errInterceptor, logInterceptor, statsInterceptor)

// This chain will:
// 1. Log the request.
// 2. Record stats about the request.
// 3. Do HTTP.
// 4. Retry temporary errors and return after all retries have been exhausted.
// 5. Record stats about the response.
// 6. Log the response.
transport := train.Transport(logInterceptor, statsInterceptor, errInterceptor)

Documentation

Overview

Package train provides a http.RoundTripper with chainable middleware.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Transport

func Transport(interceptors ...Interceptor) http.RoundTripper

Return a new http.RoundTripper with the given interceptors and http.DefaultTransport. Interceptors will be called in the order they are provided.

Example
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"

	"github.com/f2prateek/train"
	"github.com/f2prateek/train/log"
	"github.com/gohttp/response"
)

func main() {
	client := &http.Client{
		// Try changing the log level!
		Transport: train.Transport(log.New(os.Stdout, log.None)),
	}

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		response.OK(w, "Hello World!")
	}))
	defer ts.Close()

	resp, _ := client.Get(ts.URL)
	bytes, _ := ioutil.ReadAll(resp.Body)

	fmt.Println(string(bytes))
}
Output:

Hello World!

func TransportWith

func TransportWith(transport http.RoundTripper, interceptors ...Interceptor) http.RoundTripper

Return a new http.RoundTripper with the given interceptors and a custom http.RoundTripper to perform the actual HTTP request. Interceptors will be called in the order they are provided.

Types

type Chain

type Chain interface {
	// Request returns the http.Request for this chain.
	Request() *http.Request
	// Proceed the chain with a given request and returns the result.
	Proceed(*http.Request) (*http.Response, error)
}

type Interceptor

type Interceptor interface {
	// Intercept the chain and return a result.
	Intercept(Chain) (*http.Response, error)
}

Observes, modifies, and potentially short-circuits requests going out and the corresponding requests coming back in. Typically interceptors will be used to add, remove, or transform headers on the request or response. Interceptors must return either a response or an error.

func RoundTripper

func RoundTripper(rt http.RoundTripper) Interceptor

RoundTripper adapts an `http.RoundTripper` to an `Interceptor`.

func UserAgent

func UserAgent(userAgent string) Interceptor

UserAgent returns an `Interceptor` that sets the user-agent on outgoing requests.

type InterceptorFunc

type InterceptorFunc func(Chain) (*http.Response, error)

The InterceptorFunc type is an adapter to allow the use of ordinary functions as interceptors. If f is a function with the appropriate signature, InterceptorFunc(f) is a Interceptor that calls f.

func (InterceptorFunc) Intercept

func (f InterceptorFunc) Intercept(c Chain) (*http.Response, error)

Intercept calls f(c).

Source Files

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to