Documentation
¶
Overview ¶
Package server provides a convienence type for merging GRPC/REST/HTTP services on a single port. This avoids issues like needing CORS for JS/WASM clients to talk REST to your service because it runs on a different port. It handles issues such as:
- Routing all three services on a single port
- Applying TLS for all services
- REST Gateway to GRPC setup
- Can not use TLS while using HTTP and GRPC services (a nightmare to figure out why it doesn't work)
- Sane HTTP/REST default compression if client supported(gzip)
- GRPC gzip compression support (though this is based on the client request using gzip)
- Applying common HTTP handler wrappers to the Gateway and HTTP handlers (or individually)
- STAYING OUT OF THE WAY to allow you to customize your GRPC server, REST Gateway and HTTP.
This package is meant to be used internally in a common GRPC platform package for a company. That parent package can automatically setup health handlers, have options for ACL processing, automatically tie into monitoring, etc...
Important Notes:
- Traffic going to REST MUST have Content-Type set to "application/grpc-gateway".
- The gateway/client located in this Repo automatically sets this.
- We do not compress content being served with file types (as discovered by file extensions) that are already compressed
Usage example:
// Basic GRPC server setup. grpcServer := grpc.NewSever() myServer := myService.NewServer() pb.RegisterMyServiceService(grpcServer, myServer) // Must happen prior to New() call. // GRPC gateway setup, if doing a REST fronend. If you haven't done this before, you // will need to follow the protocol buffer compiler setup, which is beyond the scope of this. // https://grpc-ecosystem.github.io/grpc-gateway/docs/usage.html gwMux := runtime.NewServeMux() // Setup an HTTP Server serving all other pages. httpMux := http.NewServeMux() httpMux.Handle( "/", http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello World!")) }, ), ) logCallType := func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ switch r.Header.Get("content-type") { case "application/grpc-gateway": log.Println("request serviced by REST") default: log.Println("request is a normal HTTP request") } next.ServeHTTP(w, r) // Call the wrapped http.Handler }) } united, err := New( "208.244.233.1:8080", grpcServer, // This runs without TLS. Do not do this in production!!!!!!!! WithInsecure(), // This instantiates a GRPC REST Gateway on the same port for REST clients. Gateway( gwMux, pb.RegisterMyServerHandlerFromEndpoint, nil, []grpc.DialOption{grpc.WithInsecure()}, ), // This serves an HTTP server handling everything that isn't GRPC on the same port. // This assumes that httpMux variable exists somewhere above. HTTP(httpMux, nil), // This wraps REST and HTTP calls with logCallType(). This does not wrap GRPC calls, // those must be done prior to New(). See the note on WrapHandlers(). WrapHandlers(logCallType), ) if err != nil { // Do something } // This provides a custom *http.Server. This is not required. united.SetHTTPServer( &http.Server{ ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, }, ) // This starts all the servers. This will return, so if you do this in main() you // will need a select{} or something to prevent main() from returning. if err := united.Start(); err != nil { // Do something }
Index ¶
- type Compressor
- type Decompressor
- type GRPC
- type GWRegistrationFunc
- type HTTPWrapper
- type Option
- func Gateway(mux *runtime.ServeMux, fn GWRegistrationFunc, wrappers []HTTPWrapper, ...) Option
- func HTTP(mux *http.ServeMux, wrappers []HTTPWrapper) Option
- func HTTPCompress(encodingType string, compressor Compressor) Option
- func HTTPDecompress(encodingType string, decompressor Decompressor) Option
- func WithInsecure() Option
- func WithTLS(certs []tls.Certificate) Option
- func WrapHandlers(handlers ...HTTPWrapper) Option
- type ResponseWriter
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Compressor ¶
type Compressor func(w http.ResponseWriter) ResponseWriter
Compressor provides a function that composes an io.WriteCloser representing a compressor and the http.ResponseWriter into our local ResponseWriter that implements http.ResponseWriter with an additional Close() method for closing the compressor writes.
type Decompressor ¶
Decompressor takes an io.Reader and either compresses the content or decompresses the content to the returned io.ReadCloser.
type GRPC ¶
type GRPC struct {
// contains filtered or unexported fields
}
GRPC wraps a GRPC server and optionally a GRPC Gateway and HTTP server on a single port.
func New ¶
New is the constructor for GRPC. pb.Register<Name>Service() must have been called on the serv argument.
func (*GRPC) ListeningOn ¶
ListeningOn is the address this GRPC server is currently listening on. Will return nil if it is not serving.
func (*GRPC) SetHTTPServer ¶
SetHTTPServer allows you to provide a custom *http.Server. The fields Addr, Handler and TLSConfig in the http.Server will be overridden no matter what is provided here. If not provided, a default one is provided with just Handler and TLSConfig configured. This does not work after Start() has been called.
type GWRegistrationFunc ¶
type GWRegistrationFunc func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) error
GWRegistrationFunc is a function in your <service>.pb.gw.go file that is used to register a GRPC REST gateway to talk to the GRPC service. It is usually named Register<service>HandlerFromEndpoint().
type HTTPWrapper ¶
HTTPWrapper provides an http.Hanlder that wraps another http.Handler. It is the responsibility of the HTTPWrapper implementation to call the wrapped Handler (or not to). A good reference on this pattern can be found at https://medium.com/@matryer/the-http-handler-wrapper-technique-in-golang-updated-bc7fbcffa702 .
type Option ¶
type Option func(g *GRPC)
Option provides an optional argument for the GRPC constructor.
func Gateway ¶
func Gateway(mux *runtime.ServeMux, fn GWRegistrationFunc, wrappers []HTTPWrapper, dialOptions []grpc.DialOption) Option
Gateway provides a GRPC REST gateway proxy that will answer all calls that have the header Content-Type set to "application/grpc-gateway". fn is a functions that registers this gateway with the GRPC server (see comments on GWRegistrationFunc type). wrappers are http.Handler(s) that you want to wrap the gateway (like authoriztion or acl handlers). If you want to wrap both the gateway and an HTTP server in the same handlers instead use the WrapHandlers() option. Note: handlers that do response compression or decompression should be added with the HTTPCompress() and HTTPDecompress() options. dialOptions provides options that are needed to dial your GRPC service from the gateway. You may need to provide dialOptions like grpc.WithInsecure() if you are using the WithInsecure() option above.
func HTTP ¶
func HTTP(mux *http.ServeMux, wrappers []HTTPWrapper) Option
HTTP installs an http.ServeMux to handle all calls that do not have "application/grpc-gateway" or "application/grpc". wrappers provides http.Handler(s) that you want to wrap the mux in. If you want to install wrapper handlers on both the REST gateway and this ServeMux, you should use WrapHandlers(). Note: handlers that do response compression should be added with the HTTPCompress() option.
func HTTPCompress ¶
func HTTPCompress(encodingType string, compressor Compressor) Option
HTTPCompress compresses responses to HTTP clients if the client sent an Accept-Encoding for the type. Order of preference for the compress method will be: 1) The same as encoding on the request if provided, 2) The order they were added with this option.
func HTTPDecompress ¶
func HTTPDecompress(encodingType string, decompressor Decompressor) Option
HTTPDecompress decompresses requests coming from the clients for REST matching on the client request's Encoding-Type. This puts a http.Handler before all other handlers provided to do the decompression. "gzip" and "deflate" are automatically provided.
func WithInsecure ¶
func WithInsecure() Option
WithInsecure is required in order to run without a TLS certificate.
func WithTLS ¶
func WithTLS(certs []tls.Certificate) Option
WithTLS secures all services (GRPC/REST/HTTP) with the TLS certificates passed. If this option is not used, WithInsecure must be used.
func WrapHandlers ¶
func WrapHandlers(handlers ...HTTPWrapper) Option
WrapHandlers wraps both the muxer passed with Gateway() and the the muxer passed to HTTP() with the handlers passed here. Note: handlers that do response compression should be added with the HTTPCompress() option. To wrap GRPC itself, you must use an UnaryServerInterceptor (defined at https://godoc.org/google.golang.org/grpc#UnaryServerInterceptor). You wrap it on the server using the UnaryInterceptor() ServerOption (https://godoc.org/google.golang.org/grpc#UnaryInterceptor) when doing grpc.NewServer().
type ResponseWriter ¶
type ResponseWriter interface { io.WriteCloser http.ResponseWriter }
ResponseWriter is a composition of an io.WriteCloser and http.ResponseWriter. This is used when trying to define a new response compression. See examples in the compress.go file.