vhost

package module
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

README

go-vhost

go-vhost is a simple library that lets you implement virtual hosting functionality for different protocols (HTTP and TLS so far). go-vhost has a high-level and a low-level interface. The high-level interface lets you wrap existing net.Listeners with "muxer" objects. You can then Listen() on a muxer for a particular virtual host name of interest which will return to you a net.Listener for just connections with the virtual hostname of interest.

The lower-level go-vhost interface are just functions which extract the name/routing information for the given protocol and return an object implementing net.Conn which works as if no bytes had been consumed.

API Documentation
Usage
l, _ := net.Listen("tcp", *listen)

// start multiplexing on it
mux, _ := vhost.NewHTTPMuxer(l, muxTimeout)

// listen for connections to different domains
for _, v := range virtualHosts {
	vhost := v

	// vhost.Name is a virtual hostname like "foo.example.com"
	muxListener, _ := mux.Listen(vhost.Name())

	go func(vh virtualHost, ml net.Listener) {
		for {
			conn, _ := ml.Accept()
			go vh.Handle(conn)
		}
	}(vhost, muxListener)
}

for {
	conn, err := mux.NextError()

	switch err.(type) {
	case vhost.BadRequest:
		log.Printf("got a bad request!")
		conn.Write([]byte("bad request"))
	case vhost.NotFound:
		log.Printf("got a connection for an unknown vhost")
		conn.Write([]byte("vhost not found"))
	case vhost.Closed:
		log.Printf("closed conn: %s", err)
	default:
		if conn != nil {
			conn.Write([]byte("server error"))
		}
	}

	if conn != nil {
		conn.Close()
	}
}
Low-level API usage
// accept a new connection
conn, _ := listener.Accept()

// parse out the HTTP request and the Host header
if vhostConn, err = vhost.HTTP(conn); err != nil {
	panic("Not a valid http connection!")
}

fmt.Printf("Target Host: ", vhostConn.Host())
// Target Host: example.com

// vhostConn contains the entire request as if no bytes had been consumed
bytes, _ := ioutil.ReadAll(vhostConn)
fmt.Printf("%s", bytes)
// GET / HTTP/1.1
// Host: example.com
// User-Agent: ...
// ...
Advanced introspection

The entire HTTP request headers are available for inspection in case you want to mux on something besides the Host header:

// parse out the HTTP request and the Host header
if vhostConn, err = vhost.HTTP(conn); err != nil {
	panic("Not a valid http connection!")
}

httpVersion := vhost.Request.MinorVersion
customRouting := vhost.Request.Header["X-Custom-Routing-Header"]

Likewise for TLS, you can look at detailed information about the ClientHello message:

if vhostConn, err = vhost.TLS(conn); err != nil {
	panic("Not a valid TLS connection!")
}

cipherSuites := vhost.ClientHelloMsg.CipherSuites
sessionId := vhost.ClientHelloMsg.SessionId
Memory reduction with Free

After you're done muxing, you probably don't need to inspect the header data anymore, so you can make it available for garbage collection:

// look up the upstream host
upstreamHost := hostMapping[vhostConn.Host()]

// vhostConn.Host() == ""
// vhostConn.Request == nil (HTTP)
// vhostConn.ClientHelloMsg == nil (TLS)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ClientHelloMsg

type ClientHelloMsg struct {
	Raw                []byte
	Vers               uint16
	Random             []byte
	SessionId          []byte
	CipherSuites       []uint16
	CompressionMethods []uint8
	NextProtoNeg       bool
	ServerName         string
	OcspStapling       bool
	SupportedCurves    []uint16
	SupportedPoints    []uint8
	TicketSupported    bool
	SessionTicket      []uint8
}

type HTTPInfo added in v1.3.0

type HTTPInfo struct {
	Request *http.Request
	// contains filtered or unexported fields
}

func HTTP

func HTTP(conn net.Conn) (httpConn *HTTPInfo, err error)

HTTP parses the head of the first HTTP request on conn and returns a new, unread connection with metadata for virtual host muxing

func (*HTTPInfo) HeaderData added in v1.3.0

func (c *HTTPInfo) HeaderData() []byte

func (*HTTPInfo) Host added in v1.3.0

func (c *HTTPInfo) Host() string

type Info added in v1.3.0

type Info interface {
	Host() string
	HeaderData() []byte
}

type TLSInfo added in v1.3.0

type TLSInfo struct {
	ClientHelloMsg *ClientHelloMsg
	// contains filtered or unexported fields
}

A Conn represents a secured connection. It implements the net.Conn interface.

func TLS

func TLS(conn net.Conn) (tlsConn *TLSInfo, err error)

TLS parses the ClientHello message on conn and returns a new, unread connection with metadata for virtual host muxing

func (*TLSInfo) HeaderData added in v1.3.0

func (c *TLSInfo) HeaderData() []byte

func (*TLSInfo) Host added in v1.3.0

func (c *TLSInfo) Host() string

Jump to

Keyboard shortcuts

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