func New(auth auth.Authenticator, services []*Service, serveStatic bool,
	staticRoot string) (*Proxy, error) {
	staticServer := http.NotFoundHandler()
	if serveStatic {
		if len(strings.TrimSpace(staticRoot)) == 0 {
			return nil, fmt.Errorf("staticroot cannot be empty, " +
				"must contain path to directory that " +
				"contains index.html")
		}
		staticServer = http.FileServer(http.Dir(staticRoot))
	}
	proxy := &Proxy{
		staticServer:  staticServer,
		authenticator: auth,
		services:      services,
	}
	err := proxy.UpdateServices(services)
	if err != nil {
		return nil, err
	}
	return proxy, nil
}
New returns a new Proxy instance that proxies between the services specified,
using the auth to validate each request's headers and get new challenge
headers if necessary.
package proxy
import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"regexp"
	"strconv"
	"strings"
	"github.com/lightninglabs/aperture/auth"
	"github.com/lightninglabs/aperture/lsat"
	"google.golang.org/grpc/codes"
)
const (
	formatPattern  = "- - \"%s %s %s\" \"%s\" \"%s\""
	hdrContentType = "Content-Type"
	hdrGrpcStatus  = "Grpc-Status"
	hdrGrpcMessage = "Grpc-Message"
	hdrTypeGrpc    = "application/grpc"
)
type Proxy struct {
	proxyBackend  *httputil.ReverseProxy
	staticServer  http.Handler
	authenticator auth.Authenticator
	services      []*Service
}