spdy

package module
v0.0.0-...-b5edf18 Latest Latest
Warning

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

Go to latest
Published: Feb 17, 2016 License: BSD-2-Clause Imports: 16 Imported by: 17

README

Deprecated

With the release of Go1.6 and the addition of http2 to the standard library, this package is no longer under active development. It is highly recommended that former users of this package migrate to HTTP/2.

spdy

GoDoc

A full-featured SPDY library for the Go language.

Note that this implementation currently supports SPDY drafts 2 and 3.

See these examples for a quick intro to the package.

Note that using this package with Martini is likely to result in strange and hard-to-diagnose bugs. For more information, read this article. 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 an empty struct.
	if ping, err := spdy.PingClient(w); err == nil {
		select {
		case response := <- ping:
			if response != nil {
				// 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()
	
	// ...
}

Documentation

Overview

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

Constants

View Source
const DEFAULT_SPDY_VERSION = 3.1

SPDY version of this implementation.

Variables

This section is empty.

Functions

func AddSPDY

func AddSPDY(srv *http.Server)

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

func ConnectAndServe

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

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

func EnableDebugOutput()

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

func EnableSpdyVersion

func EnableSpdyVersion(v float64) error

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

func GetPriority

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

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

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

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

func NewClient(insecureSkipVerify bool) *http.Client

NewClient creates an http.Client that supports SPDY.

func NewClientConn

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

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

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

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

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

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

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

func SetDebugLogger(l *logging.Logger)

SetDebugLogger sets the package's debug info logger.

func SetDebugOutput

func SetDebugOutput(w io.Writer)

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

func SetFlowControl

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

func SetLogOutput(w io.Writer)

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

func SetLogger

func SetLogger(l *logging.Logger)

SetLogger sets the package's error logger.

func SetMaxBenignErrors

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

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

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

func UsingSPDY(w http.ResponseWriter) bool

UsingSPDY indicates whether a given ResponseWriter is using SPDY.

Types

type Compressor

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

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

type Conn

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

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

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

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

type Pinger

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

Pinger represents something able to send and receive PING frames.

type PriorityStream

type PriorityStream interface {
	Stream

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

PriorityStream represents a SPDY stream with a priority.

type ProxyConnHandler

type ProxyConnHandler interface {
	ProxyConnHandle(Conn)
}

type ProxyConnHandlerFunc

type ProxyConnHandlerFunc func(Conn)

func (ProxyConnHandlerFunc) ProxyConnHandle

func (p ProxyConnHandlerFunc) ProxyConnHandle(c Conn)

type Pusher

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

Pusher represents something able to send server puhes.

type SetFlowController

type SetFlowController interface {
	SetFlowControl(common.FlowControl)
}

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

type Stream

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

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

func NewTransport(insecureSkipVerify bool) *Transport

NewTransport gives a simple initialised Transport.

func (*Transport) RoundTrip

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

Path Synopsis
Package common contains shared functionality for the spdy package.
Package common contains shared functionality for the spdy package.
examples
Package spdy2 contains functionality for SPDY/2.
Package spdy2 contains functionality for SPDY/2.
frames
Package frames contains an implementation of the SPDY/2 frames.
Package frames contains an implementation of the SPDY/2 frames.
Package spdy3 contains functionality for SPDY/3.
Package spdy3 contains functionality for SPDY/3.
frames
Package frames contains an implementation of the SPDY/3 frames.
Package frames contains an implementation of the SPDY/3 frames.

Jump to

Keyboard shortcuts

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