action

package
v0.0.0-...-0399f01 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2023 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Example
package main

import (
	"context"
	"net/http"
	"testing/fstest"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"zombiezen.com/go/bass/action"
)

// base.html file
const baseHTML = `<!DOCTYPE html>
<html>
	<title>
		{{- block "title" . }}{{ end -}}
	</title>
	<body>
		{{- block "body" . }}{{ end -}}
	</body>
</html>`

// index.html file
const indexHTML = `<!DOCTYPE html>
{{ define "title" -}}
	Home
{{- end }}

{{ define "body" -}}
	<h1>Hello, {{ .Subject }}!</h1>
{{- end }}`

func main() {
	// Typically, you would load these from disk
	// either by using embed or with os.DirFS.
	templateFiles := fstest.MapFS{
		"base.html":  {Data: []byte(baseHTML)},
		"index.html": {Data: []byte(indexHTML)},
	}

	// NewHandler can be used much like http.HandlerFunc,
	// but it also takes in templates.
	// For more advanced features, see action.Config.
	indexHandler := action.NewHandler(templateFiles, index)

	// Add the handler to your router of choice:
	router := mux.NewRouter()
	router.Handle("/", handlers.MethodHandler{
		http.MethodGet:  indexHandler,
		http.MethodHead: indexHandler,
	})
	http.ListenAndServe(":8080", router)
}

// index is an action.Func.
func index(ctx context.Context, r *http.Request) (*action.Response, error) {
	// Responses
	return &action.Response{
		HTMLTemplate: "index.html",
		TemplateData: map[string]any{
			"Subject": "World",
		},
	}, nil
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrNotFound = WithStatusCode(http.StatusNotFound, errors.New("404 not found"))

ErrNotFound is a generic "not found" error that can be returned from a Func to render an HTTP 404 (Not Found) response.

Functions

func ErrorStatusCode

func ErrorStatusCode(err error) int

ErrorStatusCode finds the first error in err's chain that was created by WithStatusCode, and if one is found, returns the HTTP status code. If err is nil, it returns 200 (OK). Otherwise, it returns 500 (Internal Server Error).

func WithStatusCode

func WithStatusCode(code int, err error) error

WithStatusCode returns an error for which ErrorStatusCode returns the given code and errors.Unwrap returns the given error.

Types

type Config

type Config[R any] struct {
	// TransformRequest converts an [*http.Request] to the [Func]'s request type.
	// If R is *http.Request and TransformRequest is nil,
	// then the *http.Request is used verbatim.
	// Otherwise, if TransformRequest is nil, the Handler will serve errors.
	//
	// TransformRequest may return a cleanup function,
	// which will be called after the [Func] is called
	// to release any resources associated with the returned request.
	//
	// If TransformRequest returns an error that is not given a status code with [WithStatusCode],
	// then 400 (Bad Request) is assumed.
	TransformRequest func(*http.Request) (request R, cleanup func(), err error)

	// If MaxRequestSize is greater than zero,
	// then Handler will place an [http.MaxBytesReader] on the request body
	// before it is sent to TransformRequest.
	MaxRequestSize int64

	// TransformError is an optional callback to convert errors into responses.
	// If nil, a basic plain text conversion will be performed
	// that uses the status code from [ErrorStatusCode].
	//
	// Templated error responses can only use funcs from TemplateFuncs,
	// not MakeRequestTemplateFuncs,
	// because TransformError may be called prior to TransformRequest
	// in case of a bad request.
	TransformError func(error) *Response

	// TemplateFiles is used for reading templates for responses.
	// It is only needed if the handler uses the template fields in [Response].
	TemplateFiles fs.FS

	// TemplateFuncs is a set of functions available in every response.
	TemplateFuncs template.FuncMap

	// MakeRequestTemplateFuncs is a callback that produces a set of functions
	// available in responses returned from the handler's [Func].
	MakeRequestTemplateFuncs func(context.Context, R) template.FuncMap

	// ReportError is an optional callback
	// for application errors that occur during request processing.
	ReportError func(context.Context, error)
}

A Config contains options for creating a Handler. The Config type is parameterized on request type.

func (*Config[R]) NewHandler

func (cfg *Config[R]) NewHandler(f Func[R]) *Handler[R]

NewHandler creates a Handler with the given function.

type ForceAccept

type ForceAccept struct {
	Accept  string
	Handler http.Handler
}

ForceAccept is an HTTP middleware that unconditionally sets the Accept request header to a given string.

func ForceJSON

func ForceJSON(h http.Handler) *ForceAccept

ForceJSON wraps a handler with a ForceAccept with a JSON content type.

func (*ForceAccept) ServeHTTP

func (fa *ForceAccept) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP calls fa.Handler.ServeHTTP with a copy of r where the Accept header is set to fa.Accept.

type Func

type Func[R any] func(context.Context, R) (*Response, error)

type Handler

type Handler[R any] struct {
	// contains filtered or unexported fields
}

A Handler responds to an HTTP request by calling a Func.

func NewHandler

func NewHandler(templateFiles fs.FS, f Func[*http.Request]) *Handler[*http.Request]

NewHandler returns a new Handler with a default Config that calls f.

func (*Handler[R]) ServeHTTP

func (h *Handler[R]) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handles an HTTP request.

type Representation

type Representation struct {
	Header http.Header
	Body   io.ReadCloser
}

A Representation is a representation of a Response. The Header must contain a value for Content-Type for it to be used.

func TextRepresentation

func TextRepresentation(s string) *Representation

TextRepresentation creates a plain text representation of a string.

func (*Representation) Write

func (repr *Representation) Write(w http.ResponseWriter, code int) error

Write copies the representation to the response writer.

type Response

type Response struct {
	// StatusCode is the response's HTTP status code.
	// If it is zero and SeeOther is not empty, then 303 (See Other) is assumed,
	// otherwise 200 (OK).
	StatusCode int
	// SeeOther specifies the response's [Location header].
	// If it is not empty, then the response is a redirect.
	//
	// [Location header]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location
	SeeOther string

	// SetCookies is a list of cookies to add as Set-Cookie headers.
	// The provided cookies must have valid names.
	// Invalid cookies may be silent dropped.
	SetCookies []*http.Cookie

	// TemplateData is passed to the templates.
	// See [text/template] for details.
	TemplateData any
	// HTMLTemplate names an html/template file to use to present HTML.
	HTMLTemplate string
	// TurboStreamTemplate names an html/template file to use to present Turbo Stream data.
	TurboStreamTemplate string
	// TextTemplate names a text/template file to use to present plain text.
	TextTemplate string
	// JSONValue is a value to marshal to present JSON.
	JSONValue any

	// Other lists representations of the response.
	Other []*Representation
}

Response represents an HTTP response. It contains zero or more representations of its resource, which will be selected via content negotiation. A nil or zero Response represents an HTTP 204 (No Content) response.

func (*Response) Close

func (resp *Response) Close() error

Close closes the bodies of all representations, returning the first error encountered.

func (*Response) IsEmpty

func (resp *Response) IsEmpty() bool

IsEmpty reports whether the response is nil or does not have any valid representations.

func (*Response) IsRedirect

func (resp *Response) IsRedirect() bool

IsRedirect reports whether resp.SeeOther is not empty.

Jump to

Keyboard shortcuts

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