httphandler

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2025 License: MIT Imports: 9 Imported by: 0

README

go-httphandler

GoDoc Go Report Card License

A zero-dependency HTTP response handler for Go that makes writing HTTP handlers idiomatic and less error-prone.

Features

  • Zero Dependencies: Built entirely on Go's standard library
  • 📄 Built-in Response Types: Support for JSON, plain text, file downloads, and redirects
  • 🛠️ Fluent API: Chain methods to customize responses with headers, cookies, and status codes
  • 🔄 Flexible Request Parsing: Built-in JSON parsing with support for custom decoders
  • 🧩 Easily Extendable: Create custom response types and request decoders
  • 📝 Integrated Logging: Optional logging support for all response types
  • 🔗 Request Pipeline Architecture: Type-safe middleware-like functionality using Go's generics

Why go-httphandler?

Traditional Go HTTP handlers interact directly with http.ResponseWriter, which can lead to several common pitfalls:

// Traditional approach - common pitfalls

// Pitfall 1: Headers must be set before writing the response
router.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {
    user := getUser(r.PathValue("id"))
    if user == nil {
        json.NewEncoder(w).Encode(map[string]string{
            "error": "User not found",
        })
        w.WriteHeader(http.StatusNotFound) // Bug: Too late! Headers can't be set after writing response
        return
    }
    json.NewEncoder(w).Encode(user)
})

// Pitfall 2: Missing returns cause code to continue executing
router.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {
    user := getUser(r.PathValue("id"))
    if user == nil {
        w.WriteHeader(http.StatusNotFound)
        json.NewEncoder(w).Encode(map[string]string{
            "error": "User not found",
        })
        // Missing return! Code continues executing...
    }
    
    // This will still execute!
    json.NewEncoder(w).Encode(user)
})

// go-httphandler approach - prevents both issues by design
router.HandleFunc("GET /users/{id}", httphandler.Handle(func(r *http.Request) httphandler.Responder {
    user := getUser(r.PathValue("id"))
    if user == nil {
        return jsonresp.Error(nil, &ErrorResponse{
            Code:    "NOT_FOUND",
            Message: "User not found",
        }, http.StatusNotFound)
    }
    return jsonresp.Success(user)
}))

Installation

go get github.com/alvinchoong/go-httphandler

Usage Examples

Response Types
JSON Response
func getUserHandler(r *http.Request) httphandler.Responder {
    user, err := getUser(r.PathValue("id"))
    if err != nil {
        return jsonresp.InternalServerError(err)
    }
    if user == nil {
        return jsonresp.Error(nil, &ErrorResponse{
            Code:    "NOT_FOUND",
            Message: "User not found",
        }, http.StatusNotFound)
    }
    return jsonresp.Success(user)
}

router.HandleFunc("GET /users/{id}", httphandler.Handle(getUserHandler))
File Response
func downloadReportHandler(r *http.Request) httphandler.Responder {
    file := getReport()
    return downloadresp.Attachment(file, "report.pdf").
        WithContentType("application/pdf")
}
Redirect Response
func redirectHandler(r *http.Request) httphandler.Responder {
    return httphandler.Redirect("/new-location", http.StatusTemporaryRedirect).
        WithCookie(&http.Cookie{Name: "session", Value: "123"})
}
Plain Text Response
func healthCheckHandler(r *http.Request) httphandler.Responder {
    return plainresp.Success("OK").
        WithHeader("Cache-Control", "no-cache")
}
Response Customization

All responders support method chaining for customization:

return jsonresp.Success(data).
    WithStatus(http.StatusAccepted).
    WithHeader("X-Custom-Header", "value").
    WithCookie(&http.Cookie{Name: "session", Value: "123"}).
    WithLogger(logger)
Request Handling
JSON Request Parsing
func createUserHandler(r *http.Request, input CreateUserInput) httphandler.Responder {
    if err := input.Validate(); err != nil {
        return jsonresp.Error(err, &ValidationError{
            Code:    "VALIDATION_ERROR",
            Message: "Invalid input",
            Details: err.Error(),
        }, http.StatusBadRequest)
    }
    
    user, err := createUser(input)
    if err != nil {
        return jsonresp.InternalServerError(err)
    }

    return jsonresp.Success(user)
}

router.HandleFunc("POST /users", httphandler.HandleWithInput(createUserHandler))
Additional Examples

For more examples see:

Creating Custom Response Types

You can easily create your own response types by implementing the Responder interface.

Custom CSV Responder
// Define your custom responder
type CSVResponder struct {
    records    [][]string
    filename   string
    statusCode int
}

// Create a constructor
func NewCSVResponse(records [][]string, filename string) *CSVResponder {
    return &CSVResponder{
        records:    records,
        filename:   filename,
        statusCode: http.StatusOK,
    }
}

// Implement the Responder interface
func (res *CSVResponder) Respond(w http.ResponseWriter, r *http.Request) {
    // Set headers for CSV download
    w.Header().Set("Content-Type", "text/csv")
    w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, res.filename))
    
    // Write status code
    w.WriteHeader(res.statusCode)
    
    // Write CSV
    writer := csv.NewWriter(w)
    if err := writer.WriteAll(res.records); err != nil {
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }
}

// Usage example
func csvReportHandler(r *http.Request) httphandler.Responder {
    records := [][]string{
        {"Name", "Email", "Age"},
        {"John Doe", "[email protected]", "30"},
        {"Jane Doe", "[email protected]", "28"},
    }

    return NewCSVResponse(records, "users.csv")
}

Request Pipeline Architecture

The Request Pipeline Architecture provides a powerful way to chain HTTP request processing stages while maintaining type safety using Go's generics. This enables middleware-like functionality where each stage extracts and validates part of the request, accumulating context for your handler.

Pipeline Types
// Create a pipeline with one context type (e.g., Tenant)
tenantPipeline := httphandler.NewPipeline1(DecodeTenant)

// Add a second context type (e.g., User)
userPipeline := httphandler.NewPipeline2(tenantPipeline, DecodeUser)

// Add a third context type (e.g., Product)
productPipeline := httphandler.NewPipeline3(userPipeline, DecodeProduct)
Handler Registration
// Handler with tenant and user context plus input data
router.HandleFunc("POST /products", httphandler.HandlePipelineWithInput2(
    userPipeline,
    DecodeProductInput,
    func(ctx context.Context, tenant Tenant, user User, input ProductInput) httphandler.Responder {
        // Handler receives request context, decoded tenant, user, and input data
        // Your business logic here
        return jsonresp.Success(result)
    },
))

// Handler with tenant, user, and product context plus input data
router.HandleFunc("PUT /products/{id}", httphandler.HandlePipelineWithInput3(
    productPipeline,
    DecodeProductInput,
    func(ctx context.Context, tenant Tenant, user User, product Product, input ProductInput) httphandler.Responder {
        // Handler receives request context, decoded tenant, user, product, and input data
        // Your business logic here
        return jsonresp.Success(result)
    },
))
Benefits
  • Type-Safe: All context and input values are fully typed
  • Composable: Build and reuse pipeline stages across routes
  • Error Handling: Each stage can return errors that are automatically converted to HTTP responses
  • Separation of Concerns: Validate request context before handler execution

For a complete example of the Request Pipeline Architecture, see examples/pipeline/main.go and its documentation. return NewCSVResponse(records, "users.csv") }


## Benchmarks

Performance comparison between standard Go HTTP handlers and `go-httphandler` (benchmarked on Apple M3 Pro):

```plain
BenchmarkJSONResponse/Go/StandardHTTPHandler                1167090      1013 ns/op      6118 B/op      18 allocs/op
BenchmarkJSONResponse/HTTPHandler/JSONResponse              1000000      1077 ns/op      6239 B/op      21 allocs/op
BenchmarkJSONRequest/Go/StandardHTTPHandler/JSONDecode       976839      1272 ns/op      6275 B/op      22 allocs/op
BenchmarkJSONRequest/HTTPHandler/JSONBodyDecode              926830      1250 ns/op      6379 B/op      26 allocs/op

Results show that go-httphandler adds a minimal and neglible overhead (< 100 nanoseconds) while providing significant safety and maintainability benefits.

You can validate these results on your system by running:

go test -bench=. -benchmem

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrJSONDecode = errors.New("fail to decode json")

Functions

func BasicAuth added in v0.3.0

func BasicAuth(r *http.Request) (struct {
	Username string
	Password string
}, error,
)

BasicAuth returns a decoder that extracts username and password from Basic Auth

func BearerToken added in v0.3.0

func BearerToken(r *http.Request) (string, error)

BearerToken returns a decoder that extracts a bearer token from the Authorization header

func BoolQueryParam added in v0.3.0

func BoolQueryParam(name string) func(r *http.Request) (bool, error)

BoolQueryParam returns a decoder that extracts a query parameter as a boolean

func Combine2 added in v0.3.0

func Combine2[T1, T2 any](
	decoder1 func(r *http.Request) (T1, error),
	decoder2 func(r *http.Request) (T2, error),
) func(r *http.Request) (struct {
	V1 T1
	V2 T2
}, error)

Combine2 combines two decoders into a single decoder that returns a struct with both results

func FloatQueryParam added in v0.3.0

func FloatQueryParam(name string) func(r *http.Request) (float64, error)

FloatQueryParam returns a decoder that extracts a query parameter as a float64

func FormFile added in v0.3.0

func FormFile(name string) func(r *http.Request) (*MultipartFile, error)

func FormValue added in v0.3.0

func FormValue(name string) func(r *http.Request) (string, error)

FormValue returns a decoder that extracts a form value

func Handle

func Handle(handler RequestHandler) http.HandlerFunc

Handle converts a RequestHandler to an http.HandlerFunc.

func HandlePipeline1 added in v0.3.0

func HandlePipeline1[C any](
	p Pipeline1[C],
	handler func(ctx context.Context, val C) Responder,
) http.HandlerFunc

HandlePipeline1 creates a handler using a pipeline with one context

func HandlePipeline2 added in v0.3.0

func HandlePipeline2[C1, C2 any](
	p Pipeline2[C1, C2],
	handler func(ctx context.Context, val1 C1, val2 C2) Responder,
) http.HandlerFunc

HandlePipeline2 creates a handler using a pipeline with two contexts

func HandlePipeline3 added in v0.3.0

func HandlePipeline3[C1, C2, C3 any](
	p Pipeline3[C1, C2, C3],
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3) Responder,
) http.HandlerFunc

HandlePipeline3 creates a handler using a pipeline with three contexts

func HandlePipeline4 added in v0.3.0

func HandlePipeline4[C1, C2, C3, C4 any](
	p Pipeline4[C1, C2, C3, C4],
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4) Responder,
) http.HandlerFunc

HandlePipeline4 creates a handler using a pipeline with four contexts

func HandlePipeline5 added in v0.3.0

func HandlePipeline5[C1, C2, C3, C4, C5 any](
	p Pipeline5[C1, C2, C3, C4, C5],
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5) Responder,
) http.HandlerFunc

HandlePipeline5 creates a handler using a pipeline with five contexts

func HandlePipeline6 added in v0.3.0

func HandlePipeline6[C1, C2, C3, C4, C5, C6 any](
	p Pipeline6[C1, C2, C3, C4, C5, C6],
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5, val6 C6) Responder,
) http.HandlerFunc

HandlePipeline6 creates a handler using a pipeline with six contexts

func HandlePipeline7 added in v0.3.0

func HandlePipeline7[C1, C2, C3, C4, C5, C6, C7 any](
	p Pipeline7[C1, C2, C3, C4, C5, C6, C7],
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5, val6 C6, val7 C7) Responder,
) http.HandlerFunc

HandlePipeline7 creates a handler using a pipeline with seven contexts

func HandlePipeline8 added in v0.3.0

func HandlePipeline8[C1, C2, C3, C4, C5, C6, C7, C8 any](
	p Pipeline8[C1, C2, C3, C4, C5, C6, C7, C8],
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5, val6 C6, val7 C7, val8 C8) Responder,
) http.HandlerFunc

HandlePipeline8 creates a handler using a pipeline with eight contexts

func HandlePipelineWithInput1 added in v0.3.0

func HandlePipelineWithInput1[C, T any](
	p Pipeline1[C],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val C, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput1 creates a handler with one context and input as a pipeline stage

func HandlePipelineWithInput2 added in v0.3.0

func HandlePipelineWithInput2[C1, C2, T any](
	p Pipeline2[C1, C2],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val1 C1, val2 C2, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput2 creates a handler with two contexts and input as a pipeline stage

func HandlePipelineWithInput3 added in v0.3.0

func HandlePipelineWithInput3[C1, C2, C3, T any](
	p Pipeline3[C1, C2, C3],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput3 creates a handler with three contexts and input as a pipeline stage

func HandlePipelineWithInput4 added in v0.3.0

func HandlePipelineWithInput4[C1, C2, C3, C4, T any](
	p Pipeline4[C1, C2, C3, C4],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput4 creates a handler with four contexts and input as a pipeline stage

func HandlePipelineWithInput5 added in v0.3.0

func HandlePipelineWithInput5[C1, C2, C3, C4, C5, T any](
	p Pipeline5[C1, C2, C3, C4, C5],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput5 creates a handler with five contexts and input as a pipeline stage

func HandlePipelineWithInput6 added in v0.3.0

func HandlePipelineWithInput6[C1, C2, C3, C4, C5, C6, T any](
	p Pipeline6[C1, C2, C3, C4, C5, C6],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5, val6 C6, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput6 creates a handler with six contexts and input as a pipeline stage

func HandlePipelineWithInput7 added in v0.3.0

func HandlePipelineWithInput7[C1, C2, C3, C4, C5, C6, C7, T any](
	p Pipeline7[C1, C2, C3, C4, C5, C6, C7],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5, val6 C6, val7 C7, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput7 creates a handler with seven contexts and input as a pipeline stage

func HandlePipelineWithInput8 added in v0.3.0

func HandlePipelineWithInput8[C1, C2, C3, C4, C5, C6, C7, C8, T any](
	p Pipeline8[C1, C2, C3, C4, C5, C6, C7, C8],
	inputDecoder func(r *http.Request) (T, error),
	handler func(ctx context.Context, val1 C1, val2 C2, val3 C3, val4 C4, val5 C5, val6 C6, val7 C7, val8 C8, input T) Responder,
) http.HandlerFunc

HandlePipelineWithInput8 creates a handler with eight contexts and input as a pipeline stage

func HandleWithInput

func HandleWithInput[T any](handler RequestHandlerWithInput[T], opts ...func(*handleWithInput[T])) http.HandlerFunc

HandleWithInput converts a RequestHandlerWithInput to an http.HandlerFunc.

func HeaderValue added in v0.3.0

func HeaderValue(name string) func(r *http.Request) (string, error)

HeaderValue returns a decoder that extracts a specific header value

func IntPathParam added in v0.3.0

func IntPathParam(name string) func(r *http.Request) (int, error)

IntPathParam returns a decoder that extracts a path parameter as an integer

func IntQueryParam added in v0.3.0

func IntQueryParam(name string) func(r *http.Request) (int, error)

IntQueryParam returns a decoder that extracts a query parameter as an integer

func JSONBody added in v0.3.0

func JSONBody[T any]() func(r *http.Request) (T, error)

JSONBody decodes the request body as JSON into a value of type T

func JSONBodyDecode

func JSONBodyDecode[T any](r *http.Request) (T, error)

func LogRequestError added in v0.3.0

func LogRequestError(logger Logger, err error, args ...any)

LogRequestError logs an error if a logger is provided.

func LogResponse added in v0.3.0

func LogResponse(logger Logger, status int, args ...any)

LogResponse logs the response status if a logger is provided.

func OptionalBearerToken added in v0.3.0

func OptionalBearerToken(r *http.Request) (string, error)

OptionalBearerToken returns a decoder that extracts a bearer token if present

func OptionalFormValue added in v0.3.0

func OptionalFormValue(name string) func(r *http.Request) (string, error)

OptionalFormValue returns a decoder that extracts a form value if present

func OptionalHeaderValue added in v0.3.0

func OptionalHeaderValue(name string) func(r *http.Request) (string, error)

OptionalHeaderValue returns a decoder that extracts a header value if present

func OptionalQueryParam added in v0.3.0

func OptionalQueryParam(name string) func(r *http.Request) (string, error)

OptionalQueryParam returns a decoder that extracts a query parameter value if present

func ParsedPathParam added in v0.3.0

func ParsedPathParam[T any](name string, parser func(string) (T, error)) func(r *http.Request) (T, error)

ParsedPathParam returns a decoder that extracts and parses a path parameter to a specific type

func ParsedQueryParam added in v0.3.0

func ParsedQueryParam[T any](name string, parser func(string) (T, error)) func(r *http.Request) (T, error)

ParsedQueryParam returns a decoder that extracts and parses a query parameter to a specific type

func PathParam added in v0.3.0

func PathParam(name string) func(r *http.Request) (string, error)

PathParam returns a decoder that extracts a path parameter value This works with Go 1.22's r.PathValue() method

func QueryParam added in v0.3.0

func QueryParam(name string) func(r *http.Request) (string, error)

QueryParam returns a decoder that extracts a query parameter value

func QueryParams added in v0.3.0

func QueryParams(r *http.Request) (url.Values, error)

QueryParams returns a decoder that extracts all query parameters

func Redirect

func Redirect(url string, code int) *redirectResponder

Redirect creates a new redirectResponder with the specified URL and status code.

func WithDecodeErrorHandler added in v0.3.0

func WithDecodeErrorHandler(handler func(stage int, err error) Responder) func(*PipelineOptions)

WithDecodeErrorHandler returns an option that sets a custom context error handler

func WithDecodeFunc

func WithDecodeFunc[T any](decodeFunc RequestDecodeFunc[T]) func(*handleWithInput[T])

WithDecodeFunc sets the decode function for the handler.

func WithInputErrorHandler added in v0.3.0

func WithInputErrorHandler(handler func(err error) Responder) func(*PipelineOptions)

WithInputErrorHandler returns an option that sets a custom input error handler

func WriteInternalServerError added in v0.3.0

func WriteInternalServerError(w http.ResponseWriter, logger Logger, err error, args ...any)

WriteInternalServerError writes an HTTP 500 Internal Server Error response. If a logger is provided, it will also log the error.

Types

type Logger

type Logger interface {
	Debug(msg string, args ...any)
	Info(msg string, args ...any)
	Warn(msg string, args ...any)
	Error(msg string, args ...any)
}

type MultipartFile added in v0.3.0

type MultipartFile struct {
	File   multipart.File
	Header *multipart.FileHeader
}

FormFile returns a decoder that extracts a file from a multipart form

type Pipeline1 added in v0.3.0

type Pipeline1[C any] struct {
	// contains filtered or unexported fields
}

Pipeline1 is a pipeline with one context type

func NewPipeline1 added in v0.3.0

func NewPipeline1[C any](
	decoder func(r *http.Request) (C, error),
	options ...func(*PipelineOptions),
) Pipeline1[C]

NewPipeline1 creates a pipeline with one context type

type Pipeline2 added in v0.3.0

type Pipeline2[C1, C2 any] struct {
	// contains filtered or unexported fields
}

Pipeline2 is a pipeline with two context types

func NewPipeline2 added in v0.3.0

func NewPipeline2[C1, C2 any](
	decoder1 func(r *http.Request) (C1, error),
	decoder2 func(r *http.Request, c1 C1) (C2, error),
	options ...func(*PipelineOptions),
) Pipeline2[C1, C2]

NewPipeline2 creates a pipeline with two context types

type Pipeline3 added in v0.3.0

type Pipeline3[C1, C2, C3 any] struct {
	// contains filtered or unexported fields
}

Pipeline3 is a pipeline with three context types

func NewPipeline3 added in v0.3.0

func NewPipeline3[C1, C2, C3 any](
	decoder1 func(r *http.Request) (C1, error),
	decoder2 func(r *http.Request, c1 C1) (C2, error),
	decoder3 func(r *http.Request, c1 C1, c2 C2) (C3, error),
	options ...func(*PipelineOptions),
) Pipeline3[C1, C2, C3]

NewPipeline3 creates a pipeline with three context types

type Pipeline4 added in v0.3.0

type Pipeline4[C1, C2, C3, C4 any] struct {
	// contains filtered or unexported fields
}

Pipeline4 is a pipeline with four context types

func NewPipeline4 added in v0.3.0

func NewPipeline4[C1, C2, C3, C4 any](
	decoder1 func(r *http.Request) (C1, error),
	decoder2 func(r *http.Request, c1 C1) (C2, error),
	decoder3 func(r *http.Request, c1 C1, c2 C2) (C3, error),
	decoder4 func(r *http.Request, c1 C1, c2 C2, c3 C3) (C4, error),
	options ...func(*PipelineOptions),
) Pipeline4[C1, C2, C3, C4]

NewPipeline4 creates a pipeline with four context types

type Pipeline5 added in v0.3.0

type Pipeline5[C1, C2, C3, C4, C5 any] struct {
	// contains filtered or unexported fields
}

Pipeline5 is a pipeline with five context types

func NewPipeline5 added in v0.3.0

func NewPipeline5[C1, C2, C3, C4, C5 any](
	decoder1 func(r *http.Request) (C1, error),
	decoder2 func(r *http.Request, c1 C1) (C2, error),
	decoder3 func(r *http.Request, c1 C1, c2 C2) (C3, error),
	decoder4 func(r *http.Request, c1 C1, c2 C2, c3 C3) (C4, error),
	decoder5 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4) (C5, error),
	options ...func(*PipelineOptions),
) Pipeline5[C1, C2, C3, C4, C5]

NewPipeline5 creates a pipeline with five context types

type Pipeline6 added in v0.3.0

type Pipeline6[C1, C2, C3, C4, C5, C6 any] struct {
	// contains filtered or unexported fields
}

Pipeline6 is a pipeline with six context types

func NewPipeline6 added in v0.3.0

func NewPipeline6[C1, C2, C3, C4, C5, C6 any](
	decoder1 func(r *http.Request) (C1, error),
	decoder2 func(r *http.Request, c1 C1) (C2, error),
	decoder3 func(r *http.Request, c1 C1, c2 C2) (C3, error),
	decoder4 func(r *http.Request, c1 C1, c2 C2, c3 C3) (C4, error),
	decoder5 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4) (C5, error),
	decoder6 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4, c5 C5) (C6, error),
	options ...func(*PipelineOptions),
) Pipeline6[C1, C2, C3, C4, C5, C6]

NewPipeline6 creates a pipeline with six context types

type Pipeline7 added in v0.3.0

type Pipeline7[C1, C2, C3, C4, C5, C6, C7 any] struct {
	// contains filtered or unexported fields
}

Pipeline7 is a pipeline with seven context types

func NewPipeline7 added in v0.3.0

func NewPipeline7[C1, C2, C3, C4, C5, C6, C7 any](
	decoder1 func(r *http.Request) (C1, error),
	decoder2 func(r *http.Request, c1 C1) (C2, error),
	decoder3 func(r *http.Request, c1 C1, c2 C2) (C3, error),
	decoder4 func(r *http.Request, c1 C1, c2 C2, c3 C3) (C4, error),
	decoder5 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4) (C5, error),
	decoder6 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4, c5 C5) (C6, error),
	decoder7 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4, c5 C5, c6 C6) (C7, error),
	options ...func(*PipelineOptions),
) Pipeline7[C1, C2, C3, C4, C5, C6, C7]

NewPipeline7 creates a pipeline with seven context types

type Pipeline8 added in v0.3.0

type Pipeline8[C1, C2, C3, C4, C5, C6, C7, C8 any] struct {
	// contains filtered or unexported fields
}

Pipeline8 is a pipeline with eight context types

func NewPipeline8 added in v0.3.0

func NewPipeline8[C1, C2, C3, C4, C5, C6, C7, C8 any](
	decoder1 func(r *http.Request) (C1, error),
	decoder2 func(r *http.Request, c1 C1) (C2, error),
	decoder3 func(r *http.Request, c1 C1, c2 C2) (C3, error),
	decoder4 func(r *http.Request, c1 C1, c2 C2, c3 C3) (C4, error),
	decoder5 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4) (C5, error),
	decoder6 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4, c5 C5) (C6, error),
	decoder7 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4, c5 C5, c6 C6) (C7, error),
	decoder8 func(r *http.Request, c1 C1, c2 C2, c3 C3, c4 C4, c5 C5, c6 C6, c7 C7) (C8, error),
	options ...func(*PipelineOptions),
) Pipeline8[C1, C2, C3, C4, C5, C6, C7, C8]

NewPipeline8 creates a pipeline with eight context types

type PipelineOptions added in v0.3.0

type PipelineOptions struct {
	// DecodeErrorHandler handles errors from context decoders
	DecodeErrorHandler func(stage int, err error) Responder

	// InputErrorHandler handles errors from input decoders
	InputErrorHandler func(err error) Responder
}

PipelineOptions holds configurable options for pipelines

type PipelineWithInput1 added in v0.3.0

type PipelineWithInput1[C, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput1 is a pipeline stage with one context and input

func NewPipelineWithInput1 added in v0.3.0

func NewPipelineWithInput1[C, T any](
	p Pipeline1[C],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput1[C, T]

NewPipelineWithInput1 creates a pipeline with one context type and input

type PipelineWithInput2 added in v0.3.0

type PipelineWithInput2[C1, C2, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput2 is a pipeline stage with two contexts and input

func NewPipelineWithInput2 added in v0.3.0

func NewPipelineWithInput2[C1, C2, T any](
	p Pipeline2[C1, C2],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput2[C1, C2, T]

NewPipelineWithInput2 creates a pipeline with two context types and input

type PipelineWithInput3 added in v0.3.0

type PipelineWithInput3[C1, C2, C3, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput3 is a pipeline stage with three contexts and input

func NewPipelineWithInput3 added in v0.3.0

func NewPipelineWithInput3[C1, C2, C3, T any](
	p Pipeline3[C1, C2, C3],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput3[C1, C2, C3, T]

NewPipelineWithInput3 creates a pipeline with three context types and input

type PipelineWithInput4 added in v0.3.0

type PipelineWithInput4[C1, C2, C3, C4, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput4 is a pipeline stage with four contexts and input

func NewPipelineWithInput4 added in v0.3.0

func NewPipelineWithInput4[C1, C2, C3, C4, T any](
	p Pipeline4[C1, C2, C3, C4],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput4[C1, C2, C3, C4, T]

NewPipelineWithInput4 creates a pipeline with four context types and input

type PipelineWithInput5 added in v0.3.0

type PipelineWithInput5[C1, C2, C3, C4, C5, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput5 is a pipeline stage with five contexts and input

func NewPipelineWithInput5 added in v0.3.0

func NewPipelineWithInput5[C1, C2, C3, C4, C5, T any](
	p Pipeline5[C1, C2, C3, C4, C5],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput5[C1, C2, C3, C4, C5, T]

NewPipelineWithInput5 creates a pipeline with five context types and input

type PipelineWithInput6 added in v0.3.0

type PipelineWithInput6[C1, C2, C3, C4, C5, C6, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput6 is a pipeline stage with six contexts and input

func NewPipelineWithInput6 added in v0.3.0

func NewPipelineWithInput6[C1, C2, C3, C4, C5, C6, T any](
	p Pipeline6[C1, C2, C3, C4, C5, C6],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput6[C1, C2, C3, C4, C5, C6, T]

NewPipelineWithInput6 creates a pipeline with six context types and input

type PipelineWithInput7 added in v0.3.0

type PipelineWithInput7[C1, C2, C3, C4, C5, C6, C7, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput7 is a pipeline stage with seven contexts and input

func NewPipelineWithInput7 added in v0.3.0

func NewPipelineWithInput7[C1, C2, C3, C4, C5, C6, C7, T any](
	p Pipeline7[C1, C2, C3, C4, C5, C6, C7],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput7[C1, C2, C3, C4, C5, C6, C7, T]

NewPipelineWithInput7 creates a pipeline with seven context types and input

type PipelineWithInput8 added in v0.3.0

type PipelineWithInput8[C1, C2, C3, C4, C5, C6, C7, C8, T any] struct {
	// contains filtered or unexported fields
}

PipelineWithInput8 is a pipeline stage with eight contexts and input

func NewPipelineWithInput8 added in v0.3.0

func NewPipelineWithInput8[C1, C2, C3, C4, C5, C6, C7, C8, T any](
	p Pipeline8[C1, C2, C3, C4, C5, C6, C7, C8],
	inputDecoder func(r *http.Request) (T, error),
	options ...func(*PipelineOptions),
) PipelineWithInput8[C1, C2, C3, C4, C5, C6, C7, C8, T]

NewPipelineWithInput8 creates a pipeline with eight context types and input

type RequestDecodeFunc

type RequestDecodeFunc[T any] func(r *http.Request) (T, error)

RequestDecodeFunc defines how to decode an HTTP request.

type RequestHandler

type RequestHandler func(r *http.Request) Responder

RequestHandler handles an HTTP request and returns a Responder.

type RequestHandlerWithInput

type RequestHandlerWithInput[T any] func(r *http.Request, input T) Responder

RequestHandlerWithInput handles an HTTP request with decoded input and returns a Responder.

type Responder

type Responder interface {
	Respond(w http.ResponseWriter, r *http.Request)
}

Responder defines how to respond to HTTP requests.

type ResponderFunc added in v0.3.0

type ResponderFunc func(w http.ResponseWriter, r *http.Request)

ResponderFunc is a function type that implements the Responder interface

func (ResponderFunc) Respond added in v0.3.0

func (f ResponderFunc) Respond(w http.ResponseWriter, r *http.Request)

Respond implements the Responder interface

Directories

Path Synopsis
examples
basic command
pipeline command

Jump to

Keyboard shortcuts

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