srvutil

package
Version: v0.0.0-...-402d74e Latest Latest
Warning

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

Go to latest
Published: Jan 16, 2023 License: MIT Imports: 18 Imported by: 4

Documentation

Overview

Package srvutil provides abstraction on top http.Server and mux.Router to make composable HTTP servers

Index

Examples

Constants

View Source
const (
	UserEmailHeaderKey = "x-galaxy-user-email"
	UserEmailKey       = "email"
	UUIDHeaderKey      = "x-request-id"
	PathKey            = "path"
	RouteKey           = "route"
)
View Source
const RealIPHeaderKey = "X-Real-IP"

Variables

RequestMetricsMiddleware is here for backwards compatibility.

Functions

func BuildContext

func BuildContext(r *http.Request) (context.Context, string)

func EnvVarHeaderMiddleware

func EnvVarHeaderMiddleware(vars map[string]string) func(http.Handler) http.Handler

EnvVarHeaderMiddleware will expose environment variables as HTTP response headers. It can be used with github.com/gorilla/mux:Router.Use or wrapping a Handler.

Example
package main

import (
	"log"
	"os"

	"github.com/gorilla/mux"

	"github.com/Shopify/goose/srvutil"
)

func main() {
	if os.Getenv("HOSTNAME") == "" {
		// Not all systems set the HOSTNAME env var
		hostname, err := os.Hostname()
		if err != nil {
			log.Fatal(err)
		}

		err = os.Setenv("HOSTNAME", hostname)
		if err != nil {
			log.Fatal(err)
		}
	}

	r := mux.NewRouter()
	r.Use(srvutil.EnvVarHeaderMiddleware(map[string]string{
		"HOSTNAME": "X-Hostname",
	}))
}
Output:

func LogErrorBody

func LogErrorBody(statusCode int) bool

func NewRequestMetricsMiddleware

func NewRequestMetricsMiddleware(c *RequestMetricsMiddlewareConfig) func(http.Handler) http.Handler

NewRequestMetricsMiddleware records the time taken to serve a request, and logs request and response data. Example tags: statusClass:2xx, statusCode:200 Should be added as a middleware after RequestContextMiddleware to benefit from its tags

func RealIPMiddleware

func RealIPMiddleware() func(http.Handler) http.Handler
Example
package main

import (
	"github.com/gorilla/mux"

	"github.com/Shopify/goose/srvutil"
)

func main() {
	r := mux.NewRouter()
	r.Use(srvutil.RealIPMiddleware())
}
Output:

func RequestContextMiddleware

func RequestContextMiddleware(next http.Handler) http.Handler

RequestContextMiddleware can be used with github.com/gorilla/mux:Router.Use or wrapping a Handler

func SecurityHeaderMiddleware

func SecurityHeaderMiddleware(options ...SecurityHeaderOption) func(http.Handler) http.Handler

SecurityHeaderMiddleware set default security headers.

Types

type BodyLogPredicateFunc

type BodyLogPredicateFunc func(statusCode int) bool

type DefaultRequestObserver

type DefaultRequestObserver struct{}

func (*DefaultRequestObserver) AfterRequest

func (o *DefaultRequestObserver) AfterRequest(r *http.Request, recorder HTTPRecorder, requestDuration time.Duration)

func (*DefaultRequestObserver) BeforeRequest

func (o *DefaultRequestObserver) BeforeRequest(r *http.Request)

type HTTPRecorder

type HTTPRecorder interface {
	http.ResponseWriter
	StatusCode() int
	ResponseBody() *string
}

type InlineServlet

type InlineServlet func(r *mux.Router)

func (InlineServlet) RegisterRouting

func (m InlineServlet) RegisterRouting(r *mux.Router)

type RequestMetricsMiddlewareConfig

type RequestMetricsMiddlewareConfig struct {
	BodyLogPredicate BodyLogPredicateFunc
	Observer         RequestObserver
}

type RequestObserver

type RequestObserver interface {
	BeforeRequest(*http.Request)
	AfterRequest(*http.Request, HTTPRecorder, time.Duration)
}

type SecurityHeaderOption

type SecurityHeaderOption func(headers map[string]string)

type Server

type Server interface {
	safely.Runnable
	Addr() *net.TCPAddr
}

Server wraps an http.Server to make it runnable and stoppable If its tomb dies, the server will be stopped

func NewServer

func NewServer(t *tomb.Tomb, bind string, servlet Servlet) Server
Example
tb := &tomb.Tomb{}
sl := FuncServlet("/hello/{name}", func(w http.ResponseWriter, r *http.Request) {
	name := mux.Vars(r)["name"]
	fmt.Fprintf(w, "hello %s", name)
})

sl = UseServlet(sl,
	// Should be first to properly add tags and logging fields to the context
	RequestContextMiddleware,
	NewRequestMetricsMiddleware(&RequestMetricsMiddlewareConfig{BodyLogPredicate: LogErrorBody}),
	safely.Middleware,
)

s := NewServer(tb, "127.0.0.1:0", sl)
defer s.Tomb().Kill(nil)
safely.Run(s)

u := "http://" + s.Addr().String() + "/hello/world"

res, _ := http.Get(u)
io.Copy(os.Stdout, res.Body)
Output:

hello world

func NewServerFromFactory

func NewServerFromFactory(t *tomb.Tomb, servlet Servlet, factory ServerFactory) Server

type ServerFactory

type ServerFactory func(handler http.Handler) http.Server

type Servlet

type Servlet interface {
	RegisterRouting(r *mux.Router)
}

Servlet represents a component that can handle HTTP requests It it responsible for registering on the Router.

Simple Servlets can be created with FuncServlet or HandlerServlet, but a common pattern is to have a complex struct that will initialize dependencies.

Servlets can also be modified and modified using PrefixServlet, UseServlet, and CombineServlets.

See examples.

func CombineServlets

func CombineServlets(servlets ...Servlet) Servlet

CombineServlets combines all Servlets into one, without other modifications. Great for splitting the dependency managements into smaller servlets.

func FuncServlet

func FuncServlet(path string, handler http.HandlerFunc) Servlet

FuncServlet creates a Servlet from a function.

func HandlerServlet

func HandlerServlet(path string, handler http.Handler) Servlet

HandlerServlet creates a Servlet from a Handler, which implements ServeHTTP.

Example
// Actually create a database connection
var conn dbConn

statsServlet := NewStatsPage(conn)

// Apply a middleware to a whole servlet.
var authMiddleware mux.MiddlewareFunc
statsServlet = UseServlet(statsServlet, authMiddleware)

// Register a whole Servlet under a path prefix.
statsServlet = PrefixServlet(statsServlet, "/debug")

// Combine all servlets together (if multiple)
servlet := CombineServlets(
	// NewHomePage(conn),
	statsServlet,
)

t := &tomb.Tomb{}
server := NewServer(t, "127.0.0.1:80", servlet)
safely.Run(server)
Output:

func PrefixServlet

func PrefixServlet(s Servlet, path string) Servlet

PrefixServlet registers a whole Servlet under a path prefix.

func UseServlet

func UseServlet(s Servlet, mwf ...mux.MiddlewareFunc) Servlet

UseServlet applies a middleware to a whole Servlet. Great for applying authentication layers.

Jump to

Keyboard shortcuts

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