marvin

package module
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2019 License: Apache-2.0 Imports: 21 Imported by: 7

README

GoDoc

Marvin is a go-kit server for Google App Engine

Marvin + GAE -> let's get it oooonnnn!

Marvin!

Marvin provides common tools and structure for services being built on Google App Engine by leaning heavily on the go-kit/kit/transport/http package. The service interface here is very similar to the service interface in NYT's gizmo/server/kit package so teams can build very similar looking software but use vasty different styles of infrastructure.

Marvin has been built to work with Go 1.8, which is available on App Engine Standard.

The Marvin logo is based on the Go mascot designed by Renée French and copyrighted under the Creative Commons Attribution 3.0 license.

Documentation

Index

Constants

View Source
const (
	// ContextKeyInboundAppID is populated in the context by default.
	// It contains the value of the 'X-Appengine-Inbound-Appid' header.
	ContextKeyInboundAppID contextKey = iota
)

Variables

This section is empty.

Functions

func AllowIPNets

func AllowIPNets(ipnets []*net.IPNet, denial interface{}) endpoint.Middleware

AllowIPNets is a middleware to only allow access to requests that exist in one of the given IPNets. If no IPNets are provided, all requests are allowed to pass through. If the request is denied access, the given response will be returned.

func CORSHandler

func CORSHandler(f http.Handler, originSuffix string) http.Handler

CORSHandler is a middleware func for setting all headers that enable CORS. If an originSuffix is provided, a strings.HasSuffix check will be performed before adding any CORS header. If an empty string is provided, any Origin header found will be placed into the CORS header. If no Origin header is found, no headers will be added.

func EncodeProtoRequest

func EncodeProtoRequest(_ context.Context, r *http.Request, preq interface{}) error

EncodeProtoRequest is an httptransport.EncodeRequestFunc that serializes the request as Protobuf. If the request implements Headerer, the provided headers will be applied to the request.

func EncodeProtoResponse

func EncodeProtoResponse(ctx context.Context, w http.ResponseWriter, pres interface{}) error

EncodeProtoResponse is an httptransport.EncodeResponseFunc that serializes the response as Protobuf. Many Proto-over-HTTP services can use it as a sensible default. If the response implements Headerer, the provided headers will be applied to the response. If the response implements StatusCoder, the provided StatusCode will be used instead of 200.

func Init

func Init(service Service)

Init will register the Service with a Server and register the server with App Engine. Call this in an `init()` or `main()` function.

func Internal

func Internal(ep endpoint.Endpoint, denial error) endpoint.Endpoint

Internal is a middleware handler meant to mark an endpoint or service for service-to-service use only. If the incoming request does not contain an 'X-Appengine-Inbound-Appid' header that matches the AppID of the current service, this handler will return with with the given denial response.

If no denial is given, the server will respond with a 401 status code and a simple JSON response. If you supply your own denial, we recommend you use the Proto/JSONStatusResponse structs to respond with a specific status code and the appropriate serialization.

More info on the 'X-Appengine-Inbound-Appid' header here: https://cloud.google.com/appengine/docs/standard/go/appidentity/#asserting_identity_to_other_app_engine_apps

func ParseIPNets

func ParseIPNets(ipStr string) ([]*net.IPNet, error)

ParseIPNets will accept a comma delimited list of CIDR blocks, parse them and return a slice of net.IPNets.

func ScalingHandler

func ScalingHandler(ctx context.Context, _ interface{}) (interface{}, error)

ScalingHandler is a utility endpoint for adjusting the 'min_idle_instances' of the current service on the fly. While App Engine's automatic scaling is sufficient for most uses cases, we've found that some very large bursts of traffic (i.e. the spike just after the new NYT crossword is published) cannot keep up without a large number of idle instances at the ready. To avoid the high cost of always having large amounts of idle instances, this endpoint can be used to preemptively scale your service up before a spike and then back down to normal levels post spike.

This handler expects to be registered at `/_ah/push-handlers/scale/{dir:(up|down}` as a JSON Endpoint and it expects the environment to be provisioned with `IDLE_INSTANCES_UP` and `IDLE_INSTANCES_DOWN` environment variables to set the number of min_idle_instances before and after scaling events.

This endpoint can be hit using App Engine cron for regularly recurring spikes but to make this endpoint capable of sucurely accepting pushes from PubSub, it has the `/_ah/push-handlers/` prefix.

func SetRouteVars

func SetRouteVars(r *http.Request, val map[string]string) *http.Request

SetRouteVars will set the given value into into the request context with the shared 'vars' storage key.

func Vars

func Vars(r *http.Request) map[string]string

Vars is a helper function for accessing route parameters from any server.Router implementation. This is the equivalent of using `mux.Vars(r)` with the Gorilla mux.Router.

Types

type GorillaRouter

type GorillaRouter struct {
	// contains filtered or unexported fields
}

GorillaRouter is a Router implementation for the Gorilla web toolkit's `mux.Router`.

func (*GorillaRouter) Handle

func (g *GorillaRouter) Handle(method, path string, h http.Handler)

Handle will call the Gorilla web toolkit's Handle().Method() methods.

func (*GorillaRouter) HandleFunc

func (g *GorillaRouter) HandleFunc(method, path string, h func(http.ResponseWriter, *http.Request))

HandleFunc will call the Gorilla web toolkit's HandleFunc().Method() methods.

func (*GorillaRouter) ServeHTTP

func (g *GorillaRouter) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP will call Gorilla mux.Router.ServerHTTP directly.

func (*GorillaRouter) SetNotFoundHandler

func (g *GorillaRouter) SetNotFoundHandler(h http.Handler)

SetNotFoundHandler will set the Gorilla mux.Router.NotFoundHandler.

type HTTPEndpoint

type HTTPEndpoint struct {
	Endpoint endpoint.Endpoint
	Decoder  httptransport.DecodeRequestFunc
	Encoder  httptransport.EncodeResponseFunc
	Options  []httptransport.ServerOption
}

HTTPEndpoint encapsulates everything required to build an endpoint hosted on an HTTP server.

type JSONEndpointer

type JSONEndpointer interface {
	JSONEndpoints() map[string]map[string]HTTPEndpoint
}

JSONEndpointer is for HTTP endpoints with JSON serialization The first map's string is for the HTTP path, the second is for the http method. For example:

return map[string]map[string]marvin.HTTPEndpoint{
	"/cat/{id}.json": {
		"GET": {
			Endpoint: s.GetCatByID,
			Decoder:  decodeGetCatRequest,
		},
	},
	"/cats.json": {
		"PUT": {
			Endpoint: s.PutCats,
			Decoder:  decodePutCatsProtoRequest,
		},
		"GET": {
			Endpoint: s.GetCats,
			Decoder:  decodeGetCatsRequest,
		},
	},
}

type JSONService

type JSONService interface {
	Service
	JSONEndpointer
}

JSONService endpoints are for HTTP endpoints with JSON serialization. This service will add default decoder/encoders if none provided.

type JSONStatusResponse

type JSONStatusResponse struct {
	// contains filtered or unexported fields
}

JSONStatusResponse implements: `httptransport.StatusCoder` to allow users to respond with the given response with a non-200 status code. `json.Marshaler` so it can wrap JSON Endpoint responses. `error` so it can be used to respond as an error within the go-kit stack.

func NewJSONStatusResponse

func NewJSONStatusResponse(res interface{}, code int) *JSONStatusResponse

NewJSONStatusResponse allows users to respond with a specific HTTP status code and a JSON serialized response.

func (*JSONStatusResponse) Error

func (c *JSONStatusResponse) Error() string

Error is to implement error

func (*JSONStatusResponse) MarshalJSON

func (c *JSONStatusResponse) MarshalJSON() ([]byte, error)

MarshalJSON is to implement json.Marshaler

func (*JSONStatusResponse) StatusCode

func (c *JSONStatusResponse) StatusCode() int

StatusCode is to implement httptransport.StatusCoder

type MixedService

type MixedService interface {
	Service
	JSONEndpointer
	ProtoEndpointer
}

MixedService combines the Proto and JSON services to allow users to expose endpoints on both JSON and Protobuf.

type ProtoEndpointer

type ProtoEndpointer interface {
	ProtoEndpoints() map[string]map[string]HTTPEndpoint
}

ProtoEndpointer is for HTTP endpoints with protobuf serialization. The first map's string is for the HTTP path, the second is for the http method. For example:

return map[string]map[string]marvin.HTTPEndpoint{
	"/cat/{id}.proto": {
		"GET": {
			Endpoint: s.GetCatByID,
			Decoder:  decodeGetCatRequest,
		},
	},
	"/cats.proto": {
		"PUT": {
			Endpoint: s.PutCats,
			Decoder:  decodePutCatsRequest,
		},
		"GET": {
			Endpoint: s.GetCats,
			Decoder:  decodeGetCatsRequest,
		},
	},
}

type ProtoService

type ProtoService interface {
	Service
	ProtoEndpointer
}

ProtoService endpoints are for HTTP endpoints with Protobuf serialization. This service will add default decoder/encoders if none provided.

type ProtoStatusResponse

type ProtoStatusResponse struct {
	// contains filtered or unexported fields
}

ProtoStatusResponse implements: `httptransport.StatusCoder` to allow users to respond with the given response with a non-200 status code. `proto.Marshaler` and proto.Message so it can wrap a proto Endpoint responses. `json.Marshaler` so it can wrap JSON Endpoint responses. `error` so it can be used to respond as an error within the go-kit stack.

func NewProtoStatusResponse

func NewProtoStatusResponse(res proto.Message, code int) *ProtoStatusResponse

NewProtoStatusResponse allows users to respond with a specific HTTP status code and a Protobuf or JSON serialized response.

func (*ProtoStatusResponse) Error

func (c *ProtoStatusResponse) Error() string

to implement error

func (*ProtoStatusResponse) Marshal

func (c *ProtoStatusResponse) Marshal() ([]byte, error)

to implement proto.Marshaler

func (*ProtoStatusResponse) MarshalJSON

func (c *ProtoStatusResponse) MarshalJSON() ([]byte, error)

to implement json.Marshaler

func (*ProtoStatusResponse) ProtoMessage

func (c *ProtoStatusResponse) ProtoMessage()

func (*ProtoStatusResponse) Reset

func (c *ProtoStatusResponse) Reset()

to implement proto.Message

func (*ProtoStatusResponse) StatusCode

func (c *ProtoStatusResponse) StatusCode() int

to implement httptransport.StatusCoder

func (*ProtoStatusResponse) String

func (c *ProtoStatusResponse) String() string

type Router

type Router interface {
	Handle(method string, path string, handler http.Handler)
	HandleFunc(method string, path string, handlerFunc func(http.ResponseWriter, *http.Request))
	ServeHTTP(w http.ResponseWriter, r *http.Request)
	SetNotFoundHandler(handler http.Handler)
}

Router is an interface to wrap different router implementations.

type RouterOption

type RouterOption func(Router) Router

RouterOption sets optional Router overrides.

func CustomRouter

func CustomRouter(r Router) RouterOption

CustomRouter allows users to inject an alternate Router implementation.

func RouterNotFound

func RouterNotFound(h http.Handler) RouterOption

RouterNotFound will set the not found handler of the router.

func RouterSelect

func RouterSelect(name string) RouterOption

RouterSelect allows users to override the default use of the GorillaRouter with one of the other implementations.

The following router names are accepted: * `gorilla` which uses github.com/gorilla/mux (on by default) * `stdlib` to utilize the standard library's http.ServeMux

If the supplied name does not match any known router, `gorilla` will be used. If a user wishes to supply their own router implementation, the `CustomRouter` option is available.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server manages routing and initiating the request context. Users should only need to interact with this struct in testing.

See examples/reading-list/api/service_test.go for example usage.

func NewServer

func NewServer(svc Service) Server

NewServer will init the mux and register all endpoints. This gets called by Init() and should only be used within tests.

See examples/reading-list/api/service_test.go for example usage.

func (Server) ServeHTTP

func (s Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP is the entrypoint for the server. This will initiate the app engine context and hand the request off to the router.

type Service

type Service interface {
	// HTTPMiddleware is for service-wide http specific middlewares
	// for easy integration with 3rd party http.Handlers.
	HTTPMiddleware(http.Handler) http.Handler

	// Middleware is for any service-wide go-kit middlewares
	Middleware(endpoint.Endpoint) endpoint.Endpoint

	// Options are service-wide go-kit options
	Options() []httptransport.ServerOption

	// RouterOptions allows users to override the default
	// behavior and use of the GorillaRouter.
	RouterOptions() []RouterOption
}

Service is the most basic interface of a service that can be received and hosted by Google App Engine. By default, if no warmup request is provided, marvin will add a basic handler to the /_ah/warmup route for you.

type StdlibRouter

type StdlibRouter struct {
	// contains filtered or unexported fields
}

StdlibRouter is a Router implementation for the Stdlib's `http.ServeMux`.

func (*StdlibRouter) Handle

func (g *StdlibRouter) Handle(method, path string, h http.Handler)

Handle will call the Stdlib's HandleFunc() methods with a check for the incoming HTTP method. To allow for multiple methods on a single route, use 'ANY'.

func (*StdlibRouter) HandleFunc

func (g *StdlibRouter) HandleFunc(method, path string, h func(http.ResponseWriter, *http.Request))

HandleFunc will call the Stdlib's HandleFunc() methods with a check for the incoming HTTP method. To allow for multiple methods on a single route, use 'ANY'.

func (*StdlibRouter) ServeHTTP

func (g *StdlibRouter) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP will call Stdlib's ServeMux.ServerHTTP directly.

func (*StdlibRouter) SetNotFoundHandler

func (g *StdlibRouter) SetNotFoundHandler(h http.Handler)

SetNotFoundHandler will do nothing as we cannot override the stdlib not found.

Directories

Path Synopsis
examples
reading-list
Package readinglist is a generated protocol buffer package.
Package readinglist is a generated protocol buffer package.

Jump to

Keyboard shortcuts

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