spdy: github.com/SlyMarbo/spdy Index | Files | Directories

package spdy

import "github.com/SlyMarbo/spdy"

Package spdy is a full-featured SPDY library for the Go language (still under very active development).

Note that this implementation currently supports SPDY drafts 2 and 3, and support for SPDY/4, and HTTP/2.0 is upcoming.

See examples for various simple examples that use the package.

-------------------------------

Note that using this package with Martini (https://github.com/go-martini/martini) is likely to result in strange and hard-to-diagnose bugs. For more information, read http://stephensearles.com/?p=254. As a result, issues that arise when combining the two should be directed at the Martini developers.

-------------------------------

Servers

The following examples use features specific to SPDY.

Just the handler is shown.

Use SPDY's pinging features to test the connection:

package main

import (
	"net/http"
	"time"

	"github.com/SlyMarbo/spdy"
)

func Serve(w http.ResponseWriter, r *http.Request) {
	// Ping returns a channel which will send a bool.
	if ping, err := spdy.PingClient(w); err == nil {
		select {
		case _, ok := <- ping:
			if ok {
				// Connection is fine.
			} else {
				// Something went wrong.
			}

		case <-time.After(timeout):
			// Ping took too long.
		}
	} else {
		// Not SPDY.
	}

	// ...
}

Sending a server push:

package main

import (
	"net/http"

	"github.com/SlyMarbo/spdy"
)

func Serve(w http.ResponseWriter, r *http.Request) {
	// Push returns a separate http.ResponseWriter and an error.
	path := r.URL.Scheme + "://" + r.URL.Host + "/example.js"
	push, err := spdy.Push(path)
	if err != nil {
		// Not using SPDY.
	}
	http.ServeFile(push, r, "./content/example.js")

	// Note that a PushStream must be finished manually once
	// all writing has finished.
	push.Finish()

	// ...
}

Index

Package Files

client.go doc.go log.go proxy.go server.go shared_interfaces.go spdy.go transport.go versions.go

Constants

const DEFAULT_SPDY_VERSION = 3.1

SPDY version of this implementation.

func AddSPDY Uses

func AddSPDY(srv *http.Server)

AddSPDY adds SPDY support to srv, and must be called before srv begins serving.

func ConnectAndServe Uses

func ConnectAndServe(addr string, config *tls.Config, srv *http.Server) error

ConnectAndServe is used to perform connection reversal. (See Connect() for more details.)

This works very similarly to ListenAndServeTLS, except that addr and config are used to connect to the client. If srv is nil, a new http.Server is used, with http.DefaultServeMux as the handler.

func DisableSpdyVersion Uses

func DisableSpdyVersion(v float64) error

DisableSpdyVersion can be used to disable support for the given SPDY version. This process can be undone by using EnableSpdyVersion.

func EnableDebugOutput Uses

func EnableDebugOutput()

EnableDebugOutput sets the output for the package's debug info logger to os.Stdout.

func EnableSpdyVersion Uses

func EnableSpdyVersion(v float64) error

EnableSpdyVersion can re-enable support for versions of SPDY that have been disabled by DisableSpdyVersion.

func GetPriority Uses

func GetPriority(w http.ResponseWriter) (int, error)

GetPriority is used to identify the request priority of the given stream. This can be used to manually enforce stream priority, although this is already performed by the library. If the underlying connection is using HTTP, and not SPDY, GetPriority will return the ErrNotSPDY error.

A simple example of finding a stream's priority is:

     import (
             "github.com/SlyMarbo/spdy"
             "log"
             "net/http"
     )

     func httpHandler(w http.ResponseWriter, r *http.Request) {
							priority, err := spdy.GetPriority(w)
             if err != nil {
                     // Non-SPDY connection.
             } else {
                     log.Println(priority)
             }
     }

     func main() {
             http.HandleFunc("/", httpHandler)
             log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
             err := spdy.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
             if err != nil {
                     log.Fatal(err)
             }
     }

func ListenAndServeSPDYNoNPN Uses

func ListenAndServeSPDYNoNPN(addr string, certFile string, keyFile string, handler http.Handler, version, subversion int) error

ListenAndServeSPDYNoNPN creates a server that listens exclusively for SPDY and (unlike the rest of the package) will not support HTTPS.

func ListenAndServeSpdyOnly Uses

func ListenAndServeSpdyOnly(addr string, certFile string, keyFile string, handler http.Handler) error

ListenAndServeSpdyOnly listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections. Handler is typically nil, in which case the DefaultServeMux is used. Additionally, files containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate followed by the CA's certificate.

IMPORTANT NOTE: Unlike spdy.ListenAndServeTLS, this function will ONLY serve SPDY. HTTPS requests are refused.

See examples/spdy_only_server/server.go for a simple example server.

func ListenAndServeTLS Uses

func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error

ListenAndServeTLS listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections. Handler is typically nil, in which case the DefaultServeMux is used. Additionally, files containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate followed by the CA's certificate.

See examples/server/server.go for a simple example server.

func NewClient Uses

func NewClient(insecureSkipVerify bool) *http.Client

NewClient creates an http.Client that supports SPDY.

func NewClientConn Uses

func NewClientConn(conn net.Conn, push common.Receiver, version, subversion int) (common.Conn, error)

NewClientConn is used to create a SPDY connection, using the given net.Conn for the underlying connection, and the given Receiver to receive server pushes.

func NewServerConn Uses

func NewServerConn(conn net.Conn, server *http.Server, version, subversion int) (common.Conn, error)

NewServerConn is used to create a SPDY connection, using the given net.Conn for the underlying connection, and the given http.Server to configure the request serving.

func PingClient Uses

func PingClient(w http.ResponseWriter) (<-chan bool, error)

PingClient is used to send PINGs with SPDY servers. PingClient takes a ResponseWriter and returns a channel on which a spdy.Ping will be sent when the PING response is received. If the channel is closed before a spdy.Ping has been sent, this indicates that the PING was unsuccessful.

If the underlying connection is using HTTP, and not SPDY, PingClient will return the ErrNotSPDY error.

A simple example of sending a ping is:

import (
        "github.com/SlyMarbo/spdy"
        "log"
        "net/http"
)

func httpHandler(w http.ResponseWriter, req *http.Request) {
        ping, err := spdy.PingClient(w)
        if err != nil {
                // Non-SPDY connection.
        } else {
                resp, ok <- ping
                if ok {
                        // Ping was successful.
                }
        }

}

func main() {
        http.HandleFunc("/", httpHandler)
        log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
        err := spdy.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
        if err != nil {
                log.Fatal(err)
        }
}

func PingServer Uses

func PingServer(c http.Client, server string) (<-chan bool, error)

PingServer is used to send PINGs with http.Clients using. SPDY. PingServer takes a ResponseWriter and returns a channel onwhich a spdy.Ping will be sent when the PING response is received. If the channel is closed before a spdy.Ping has been sent, this indicates that the PING was unsuccessful.

If the underlying connection is using HTTP, and not SPDY, PingServer will return the ErrNotSPDY error.

If an underlying connection has not been made to the given server, PingServer will return the ErrNotConnected error.

A simple example of sending a ping is:

import (
        "github.com/SlyMarbo/spdy"
        "net/http"
)

func main() {
        resp, err := http.Get("https://example.com/")

        // ...

        ping, err := spdy.PingServer(http.DefaultClient, "https://example.com")
        if err != nil {
                // No SPDY connection.
        } else {
                resp, ok <- ping
                if ok {
                        // Ping was successful.
                }
        }
}

func ProxyConnections Uses

func ProxyConnections(handler ProxyConnHandler) http.Handler

ProxyConnections is used with ConnectAndServe in connection- reversing proxies. This returns an http.Handler which will call handler each time a client connects. The call is treated as an event loop and the connection may be terminated if the call returns. The returned Handler should then be used in a normal HTTP server, like the following:

package main

import (
  "net/http"

  "github.com/SlyMarbo/spdy"
)

func handleProxy(conn spdy.Conn) {
  // make requests...
}

func main() {
  handler := spdy.ProxyConnHandlerFunc(handleProxy)
  http.Handle("/", spdy.ProxyConnections(handler))
  http.ListenAndServeTLS(":80", "cert.pem", "key.pem", nil)
}

Use Conn.Request to make requests to the client and Conn.Conn to access the underlying connection for further details like the client's address.

func Push Uses

func Push(w http.ResponseWriter, url string) (common.PushStream, error)

Push is used to send server pushes with SPDY servers. Push takes a ResponseWriter and the url of the resource being pushed, and returns a ResponseWriter to which the push should be written.

If the underlying connection is using HTTP, and not SPDY, Push will return the ErrNotSPDY error.

A simple example of pushing a file is:

     import (
             "github.com/SlyMarbo/spdy"
             "log"
             "net/http"
     )

     func httpHandler(w http.ResponseWriter, r *http.Request) {
             path := r.URL.Scheme + "://" + r.URL.Host + "/javascript.js"
             push, err := spdy.Push(w, path)
             if err != nil {
                     // Non-SPDY connection.
             } else {
                     http.ServeFile(push, r, "./javascript.js") // Push the given file.
											push.Finish()                              // Finish the stream once used.
             }

     }

     func main() {
             http.HandleFunc("/", httpHandler)
             log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
             err := spdy.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
             if err != nil {
                     log.Fatal(err)
             }
     }

func SPDYversion Uses

func SPDYversion(w http.ResponseWriter) float64

SPDYversion returns the SPDY version being used in the underlying connection used by the given http.ResponseWriter. This is 0 for connections not using SPDY.

func SetDebugLogger Uses

func SetDebugLogger(l *logging.Logger)

SetDebugLogger sets the package's debug info logger.

func SetDebugOutput Uses

func SetDebugOutput(w io.Writer)

SetDebugOutput sets the output for the package's debug info logger.

func SetFlowControl Uses

func SetFlowControl(w http.ResponseWriter, f common.FlowControl) error

SetFlowControl can be used to set the flow control mechanism on the underlying SPDY connection.

func SetLogOutput Uses

func SetLogOutput(w io.Writer)

SetLogOutput sets the output for the package's error logger.

func SetLogger Uses

func SetLogger(l *logging.Logger)

SetLogger sets the package's error logger.

func SetMaxBenignErrors Uses

func SetMaxBenignErrors(n int)

SetMaxBenignErrors is used to modify the maximum number of minor errors each connection will allow without ending the session.

By default, the value is set to 0, disabling checks and allowing minor errors to go unchecked, although they will still be reported to the debug logger. If it is important that no errors go unchecked, such as when testing another implementation, SetMaxBenignErrors with 1 or higher.

func SupportedVersion Uses

func SupportedVersion(v float64) bool

SupportedVersion determines if the provided SPDY version is supported by this instance of the library. This can be modified with EnableSpdyVersion and DisableSpdyVersion.

func SupportedVersions Uses

func SupportedVersions() []float64

SupportedVersions will return a slice of supported SPDY versions. The returned versions are sorted into order of most recent first.

func UsingSPDY Uses

func UsingSPDY(w http.ResponseWriter) bool

UsingSPDY indicates whether a given ResponseWriter is using SPDY.

type Compressor Uses

type Compressor interface {
    io.Closer
    Compress(http.Header) ([]byte, error)
}

Compressor is used to compress the text header of a SPDY frame.

type Conn Uses

type Conn interface {
    http.CloseNotifier
    Close() error
    Conn() net.Conn
    Request(request *http.Request, receiver common.Receiver, priority common.Priority) (common.Stream, error)
    RequestResponse(request *http.Request, receiver common.Receiver, priority common.Priority) (*http.Response, error)
    Run() error
}

Connection represents a SPDY connection. The connection should be started with a call to Run, which will return once the connection has been terminated. The connection can be ended early by using Close.

func Connect Uses

func Connect(addr string, config *tls.Config, srv *http.Server) (Conn, error)

Connect is used to perform connection reversal where the client (who is normally behind a NAT of some kind) connects to a server on the internet. The connection is then reversed so that the 'server' sends requests to the 'client'. See ConnectAndServe() for a blocking version of this

type Decompressor Uses

type Decompressor interface {
    Decompress([]byte) (http.Header, error)
}

Decompressor is used to decompress the text header of a SPDY frame.

type Pinger Uses

type Pinger interface {
    Ping() (<-chan bool, error)
}

Pinger represents something able to send and receive PING frames.

type PriorityStream Uses

type PriorityStream interface {
    Stream

    // Priority returns the stream's
    // priority.
    Priority() common.Priority
}

PriorityStream represents a SPDY stream with a priority.

type ProxyConnHandler Uses

type ProxyConnHandler interface {
    ProxyConnHandle(Conn)
}

type ProxyConnHandlerFunc Uses

type ProxyConnHandlerFunc func(Conn)

func (ProxyConnHandlerFunc) ProxyConnHandle Uses

func (p ProxyConnHandlerFunc) ProxyConnHandle(c Conn)

type Pusher Uses

type Pusher interface {
    Push(url string, origin common.Stream) (common.PushStream, error)
}

Pusher represents something able to send server puhes.

type SetFlowController Uses

type SetFlowController interface {
    SetFlowControl(common.FlowControl)
}

SetFlowController represents a connection which can have its flow control mechanism customised.

type Stream Uses

type Stream interface {
    http.CloseNotifier
    http.ResponseWriter
    Close() error
    Conn() common.Conn
    ReceiveFrame(common.Frame) error
    Run() error
    State() *common.StreamState
    StreamID() common.StreamID
}

Stream contains a single SPDY stream.

type Transport Uses

type Transport struct {

    // Proxy specifies a function to return a proxy for a given
    // Request. If the function returns a non-nil error, the
    // request is aborted with the provided error.
    // If Proxy is nil or returns a nil *URL, no proxy is used.
    Proxy func(*http.Request) (*url.URL, error)

    // Dial specifies the dial function for creating TCP
    // connections.
    // If Dial is nil, net.Dial is used.
    Dial func(network, addr string) (net.Conn, error) // TODO: use

    // TLSClientConfig specifies the TLS configuration to use with
    // tls.Client. If nil, the default configuration is used.
    TLSClientConfig *tls.Config

    // DisableKeepAlives, if true, prevents re-use of TCP connections
    // between different HTTP requests.
    DisableKeepAlives bool

    // DisableCompression, if true, prevents the Transport from
    // requesting compression with an "Accept-Encoding: gzip"
    // request header when the Request contains no existing
    // Accept-Encoding value. If the Transport requests gzip on
    // its own and gets a gzipped response, it's transparently
    // decoded in the Response.Body. However, if the user
    // explicitly requested gzip it is not automatically
    // uncompressed.
    DisableCompression bool

    // MaxIdleConnsPerHost, if non-zero, controls the maximum idle
    // (keep-alive) to keep per-host.  If zero,
    // DefaultMaxIdleConnsPerHost is used.
    MaxIdleConnsPerHost int

    // ResponseHeaderTimeout, if non-zero, specifies the amount of
    // time to wait for a server's response headers after fully
    // writing the request (including its body, if any). This
    // time does not include the time to read the response body.
    ResponseHeaderTimeout time.Duration

    // Priority is used to determine the request priority of SPDY
    // requests. If nil, spdy.DefaultPriority is used.
    Priority func(*url.URL) common.Priority

    // Receiver is used to receive the server's response. If left
    // nil, the default Receiver will parse and create a normal
    // Response.
    Receiver common.Receiver

    // PushReceiver is used to receive server pushes. If left nil,
    // pushes will be refused. The provided Request will be that
    // sent with the server push. See Receiver for more detail on
    // its methods.
    PushReceiver common.Receiver
    // contains filtered or unexported fields
}

A Transport is an HTTP/SPDY http.RoundTripper.

func NewTransport Uses

func NewTransport(insecureSkipVerify bool) *Transport

NewTransport gives a simple initialised Transport.

func (*Transport) RoundTrip Uses

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip handles the actual request; ensuring a connection is made, determining which protocol to use, and performing the request.

Directories

PathSynopsis
commonPackage common contains shared functionality for the spdy package.
spdy2Package spdy2 contains functionality for SPDY/2.
spdy2/framesPackage frames contains an implementation of the SPDY/2 frames.
spdy3Package spdy3 contains functionality for SPDY/3.
spdy3/framesPackage frames contains an implementation of the SPDY/3 frames.

Package spdy imports 16 packages (graph) and is imported by 3 packages. Updated 2016-07-17. Refresh now. Tools for package owners.