httpkit

package
v0.247.0 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2024 License: Apache-2.0 Imports: 37 Imported by: 1

README

httputil

This package provides a set of utilities for working with HTTP requests and responses.

RoundTripperFunc

RoundTripperFunc is a type that allows you to create an HTTP RoundTripper from a function that takes an HTTP request and returns an HTTP response and an error. This is useful for creating custom middleware to be used with the http.Client or the http.Transport.

RetryRoundTripper

RetryRoundTripper is a type that wraps an existing http.RoundTripper and provides a mechanism for retrying failed requests. This is useful for dealing with transient errors that can occur when making HTTP requests.

The RetryRoundTripper retries requests in case of a recoverable error (such as network timeouts or temporary server errors) up to a certain number of times. If the retries exceed the maximum number of retries, the last response and error are returned.

The RetryRoundTripper considers the following errors as retriable:

  • http.ErrHandlerTimeout
  • net.ErrClosed,
  • and timeout errors

The RetryRoundTripper considers HTTP responses with the following status codes as temporary errors:

  • Internal server error
  • Bad gateway
  • Gateway timeout
  • Service unavailable
  • Insufficient storage
  • Too many requests
  • Request timeout

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultBodyReadLimit int = 16 * iokit.Megabyte

DefaultBodyReadLimit is the maximum number of bytes that a restapi.Handler will read from the requester, if the Handler.BodyReadLimit is not provided.

View Source
var DefaultRestClientHTTPClient http.Client = http.Client{
	Transport: RetryRoundTripper{
		RetryStrategy: retry.ExponentialBackoff{
			WaitTime: time.Second,
			Timeout:  time.Minute,
		},
	},
	Timeout: 25 * time.Second,
}
View Source
var DefaultSerializer = CodecDefault{
	Serializer: jsonkit.Codec{},
	MediaType:  mediatype.JSON,
}
View Source
var DefaultSerializers = map[string]Serializer{
	"application/json":                  jsonkit.Codec{},
	"application/problem+json":          jsonkit.Codec{},
	"application/x-ndjson":              jsonkit.LinesCodec{},
	"application/stream+json":           jsonkit.LinesCodec{},
	"application/json-stream":           jsonkit.LinesCodec{},
	"application/x-www-form-urlencoded": FormURLEncodedCodec{},
}
View Source
var ErrEntityAlreadyExist = errorkit.UserError{
	ID:      "entity-already-exists",
	Message: "The entity could not be created as it already exists.",
}
View Source
var ErrEntityNotFound = errorkit.UserError{
	ID:      "entity-not-found",
	Message: "The requested entity is not found in this resource.",
}
View Source
var ErrInternalServerError = errorkit.UserError{
	ID:      "internal-server-error",
	Message: "An unexpected internal server error occurred.",
}
View Source
var ErrInvalidRequestBody = errorkit.UserError{
	ID:      "invalid-request-body",
	Message: "The request body is invalid.",
}
View Source
var ErrMalformedID = errorkit.UserError{
	ID:      "malformed-id-in-path",
	Message: "The received entity id in the path is malformed.",
}
View Source
var ErrMethodNotAllowed = errorkit.UserError{
	ID:      "restapi-method-not-allowed",
	Message: "The requested RESTful method is not supported.",
}
View Source
var ErrPathNotFound = errorkit.UserError{
	ID:      "path-not-found",
	Message: "The requested path is not found.",
}
View Source
var ErrRequestEntityTooLarge = errorkit.UserError{
	ID:      "request-entity-too-large",
	Message: "The request body was larger than the size limit allowed for the server.",
}

Functions

func ErrorMapping added in v0.220.0

func ErrorMapping(ctx context.Context, err error, dto *rfc7807.DTO)

func LookupRequest added in v0.233.0

func LookupRequest(ctx context.Context) (*http.Request, bool)

LookupRequest will check if the context contains an http request. LookupRequest is mostly meant to be used from functions like Index in RestResource.

func Mount added in v0.187.0

func Mount(mux Multiplexer, pattern string, handler http.Handler)

Mount will help to register a handler on a request multiplexer in both as the concrete path to the handler and as a prefix match. example:

if pattern -> "/something"
registered as "/something" for exact match
registered as "/something/" for prefix match
Example
package main

import (
	"net/http"

	"go.llib.dev/frameless/pkg/httpkit"
)

func main() {
	var (
		apiV0 http.Handler
		webUI http.Handler
		mux   = http.NewServeMux()
	)
	httpkit.Mount(mux, "/api/v0", apiV0)
	httpkit.Mount(mux, "/ui", webUI)
}

func MountPoint added in v0.220.0

func MountPoint(mountPoint string, next http.Handler) http.Handler

func PathParams added in v0.220.0

func PathParams(ctx context.Context) map[string]string

func WithMiddleware added in v0.211.0

func WithMiddleware(handler http.Handler, ffns ...MiddlewareFactoryFunc) http.Handler

WithMiddleware will combine an http.Handler with a stack of middleware factory functions. The order in which you pass the MiddlewareFactoryFunc -s is the same as the order, they will be called during the http.Handler.ServeHTTP method call.

func WithPathParam added in v0.220.0

func WithPathParam(ctx context.Context, key, val string) context.Context

func WithRoundTripper added in v0.216.0

func WithRoundTripper(transport http.RoundTripper, rts ...RoundTripperFactoryFunc) http.RoundTripper

WithRoundTripper will combine an http.RoundTripper with a stack of middleware factory functions. The execution order is in which you pass the factory funcs.

Example
package main

import (
	"net/http"

	"go.llib.dev/frameless/pkg/httpkit"
)

func main() {

	transport := httpkit.WithRoundTripper(nil, func(next http.RoundTripper) http.RoundTripper {
		return httpkit.RoundTripperFunc(func(request *http.Request) (*http.Response, error) {
			request.Header.Set("Authorization", "<type> <credentials>")

			return next.RoundTrip(request)
		})
	})

	_ = &http.Client{
		Transport: transport,
	}

}

Types

type AccessLog

type AccessLog struct {
	Next http.Handler

	AdditionalLoggingDetail func(w http.ResponseWriter, r *http.Request) logging.Detail
}

func (AccessLog) ServeHTTP

func (mw AccessLog) ServeHTTP(w http.ResponseWriter, r *http.Request)

type ClientErrUnexpectedResponse added in v0.220.0

type ClientErrUnexpectedResponse struct {
	StatusCode int
	Body       string
	URL        *url.URL
}

func (ClientErrUnexpectedResponse) Error added in v0.220.0

func (err ClientErrUnexpectedResponse) Error() string

type CodecDefault added in v0.231.0

type CodecDefault struct {
	Serializer interface {
		codec.Codec
		codec.ListDecoderMaker
	}
	MediaType string
}

type ErrorHandler added in v0.220.0

type ErrorHandler interface {
	HandleError(w http.ResponseWriter, r *http.Request, err error)
}

type FormURLEncodedCodec added in v0.231.0

type FormURLEncodedCodec struct{}

func (FormURLEncodedCodec) Marshal added in v0.231.0

func (e FormURLEncodedCodec) Marshal(v any) ([]byte, error)

func (FormURLEncodedCodec) Unmarshal added in v0.231.0

func (e FormURLEncodedCodec) Unmarshal(data []byte, iptr any) error

type IDConverter added in v0.220.0

type IDConverter[ID any] struct {
	Format func(ID) (string, error)
	Parse  func(string) (ID, error)
}

IDConverter is an OldMapping tool that you can embed in your OldMapping implementation, and it will implement the ID encoding that will be used in the URL.

func (IDConverter[ID]) FormatID added in v0.220.0

func (m IDConverter[ID]) FormatID(id ID) (string, error)

func (IDConverter[ID]) ParseID added in v0.220.0

func (m IDConverter[ID]) ParseID(data string) (ID, error)

type IDInContext added in v0.220.0

type IDInContext[CtxKey, EntityIDType any] struct{}

IDInContext is an OldMapping tool that you can embed in your OldMapping implementation, and it will implement the context handling related methods.

func (IDInContext[CtxKey, EntityIDType]) ContextLookupID added in v0.220.0

func (cm IDInContext[CtxKey, EntityIDType]) ContextLookupID(ctx context.Context) (EntityIDType, bool)

func (IDInContext[CtxKey, EntityIDType]) ContextWithID added in v0.220.0

func (cm IDInContext[CtxKey, EntityIDType]) ContextWithID(ctx context.Context, id EntityIDType) context.Context

type IntID added in v0.220.0

type IntID[ID ~int] struct{}

IntID is an OldMapping tool that you can embed in your OldMapping implementation, and it will implement the ID encoding that will be used in the URL.

func (IntID[ID]) FormatID added in v0.220.0

func (m IntID[ID]) FormatID(id ID) (string, error)

func (IntID[ID]) ParseID added in v0.220.0

func (m IntID[ID]) ParseID(id string) (ID, error)

type Mapper added in v0.230.0

type Mapper[Entity any] interface {
	// contains filtered or unexported methods
}

Mapper is a generic interface used for representing a DTO-Entity mapping relationship. Its primary function is to allow Resource to list various mappings, each with its own DTO type, for different MIMEType values. This means we can use different DTO types within the same restful Resource handler based on different content types, making it more flexible and adaptable to support different Serialization formats.

It is implemented by DTOMapping.

type MiddlewareFactoryFunc added in v0.211.0

type MiddlewareFactoryFunc func(next http.Handler) http.Handler

MiddlewareFactoryFunc is a constructor function that is meant to wrap an http.Handler with given middleware. Its http.Handler argument represents the next middleware http.Handler in the pipeline.

type Multiplexer added in v0.211.0

type Multiplexer interface {
	Handle(pattern string, handler http.Handler)
}

Multiplexer represents a http request Multiplexer.

type RestClient added in v0.220.0

type RestClient[ENT, ID any] struct {
	// BaseURL [required] is the url base that the rest client will use to
	BaseURL string
	// HTTPClient [optional] will be used to make the http requests from the rest client.
	//
	// default: httpkit.DefaultRestClientHTTPClient
	HTTPClient *http.Client
	// MediaType [optional] is used in the related headers such as Content-Type and Accept.
	//
	// default: httpkit.DefaultSerializer.MIMEType
	MediaType string
	// Mapping [optional] is used if the ENT must be mapped into a DTO type prior to serialization.
	//
	// default: ENT type is used as the DTO type.
	Mapping dtokit.Mapper[ENT]
	// Serializer [optional] is used for the serialization process with DTO values.
	//
	// default: DefaultSerializers will be used to find a matching serializer for the given media type.
	Serializer RestClientSerializer
	// IDConverter [optional] is used to convert the ID value into a string format,
	// that can be used to path encode for requests.
	//
	// default: httpkit.IDConverter[ID]
	IDConverter idConverter[ID]
	// LookupID [optional] is used to lookup the ID value in an ENT value.
	//
	// default: extid.Lookup[ID, ENT]
	LookupID extid.LookupIDFunc[ENT, ID]
	// WithContext [optional] allows you to add data to the context for requests.
	// If you need to select a RESTful subresource and return it as a RestClient,
	// you can use this function to add the selected resource's path parameter
	// to the context using httpkit.WithPathParam.
	//
	// default: ignored
	WithContext func(context.Context) context.Context
	// PrefetchLimit is used when a methor requires fetching entities ahead.
	// If set to -1, then prefetch is disabled.
	//
	// default: 20
	PrefetchLimit int
}
Example
package main

import (
	"context"

	"go.llib.dev/frameless/pkg/dtokit"
	"go.llib.dev/frameless/pkg/httpkit"
	"go.llib.dev/frameless/pkg/httpkit/mediatype"
	"go.llib.dev/frameless/pkg/jsonkit"
	"go.llib.dev/frameless/spechelper/testent"
)

func main() {
	var (
		ctx     = context.Background()
		fooRepo = httpkit.RestClient[testent.Foo, testent.FooID]{
			BaseURL:     "https://mydomain.dev/api/v1/foos",
			MediaType:   mediatype.JSON,
			Mapping:     dtokit.Mapping[testent.Foo, testent.FooDTO]{},
			Serializer:  jsonkit.Codec{},
			IDConverter: httpkit.IDConverter[testent.FooID]{},
			LookupID:    testent.Foo.LookupID,
		}
	)

	var ent = testent.Foo{
		Foo: "foo",
		Bar: "bar",
		Baz: "baz",
	}

	err := fooRepo.Create(ctx, &ent)
	if err != nil {
		panic(err)
	}

	gotEnt, found, err := fooRepo.FindByID(ctx, ent.ID)
	if err != nil {
		panic(err)
	}
	_, _ = gotEnt, found

	err = fooRepo.Update(ctx, &ent)
	if err != nil {
		panic(err)
	}

	err = fooRepo.DeleteByID(ctx, ent.ID)
	if err != nil {
		panic(err)
	}
}
Example (Subresource)
package main

import (
	"context"

	"go.llib.dev/frameless/pkg/httpkit"
	"go.llib.dev/frameless/spechelper/testent"
)

func main() {
	barResourceClient := httpkit.RestClient[testent.Bar, testent.BarID]{
		BaseURL: "https://example.com/foos/:foo_id/bars",
		WithContext: func(ctx context.Context) context.Context {
			// here we define that this barResourceClient is the subresource of a Foo value (id=fooidvalue)
			return httpkit.WithPathParam(ctx, "foo_id", "fooidvalue")
		},
	}

	ctx := context.Background()
	_, _ = barResourceClient.FindAll(ctx)
	_, _, _ = barResourceClient.FindByID(ctx, "baridvalue")
}

func (RestClient[ENT, ID]) Create added in v0.220.0

func (r RestClient[ENT, ID]) Create(ctx context.Context, ptr *ENT) error

func (RestClient[ENT, ID]) DeleteAll added in v0.220.0

func (r RestClient[ENT, ID]) DeleteAll(ctx context.Context) error

func (RestClient[ENT, ID]) DeleteByID added in v0.220.0

func (r RestClient[ENT, ID]) DeleteByID(ctx context.Context, id ID) error

func (RestClient[ENT, ID]) FindAll added in v0.220.0

func (r RestClient[ENT, ID]) FindAll(ctx context.Context) (iterators.Iterator[ENT], error)

func (RestClient[ENT, ID]) FindByID added in v0.220.0

func (r RestClient[ENT, ID]) FindByID(ctx context.Context, id ID) (ent ENT, found bool, err error)

func (RestClient[ENT, ID]) FindByIDs added in v0.231.0

func (r RestClient[ENT, ID]) FindByIDs(ctx context.Context, ids ...ID) (iterators.Iterator[ENT], error)

func (RestClient[ENT, ID]) Update added in v0.220.0

func (r RestClient[ENT, ID]) Update(ctx context.Context, ptr *ENT) error

type RestClientSerializer added in v0.220.0

type RestClientSerializer interface {
	codec.Codec
	codec.ListDecoderMaker
}

type RestResource added in v0.220.0

type RestResource[Entity, ID any] struct {
	// Create will create a new entity in the restful resource.
	// 		POST /
	Create func(ctx context.Context, ptr *Entity) error
	// Index will return the entities, optionally filtered with the query argument.
	//		GET /
	Index func(ctx context.Context) (iterators.Iterator[Entity], error)
	// Show will return a single entity, looked up by its ID.
	// 		GET /:id
	Show func(ctx context.Context, id ID) (ent Entity, found bool, err error)
	// Update will update/replace an entity with the new state.
	// 		PUT   /:id - update/replace
	// 		PATCH /:id - partial update (WIP)
	Update func(ctx context.Context, ptr *Entity) error
	// Destroy will delete an entity, identified by its id.
	// 		 Delete /:id
	Destroy func(ctx context.Context, id ID) error
	// DestroyAll will delete all entity.
	// 		 Delete /
	DestroyAll func(ctx context.Context) error

	// Serialization is responsible to serialize and unserialize dtokit.
	// JSON, line separated JSON stream and FormUrlencoded formats are supported out of the box.
	//
	// Serialization is an optional field.
	// Unless you have specific needs in serialization, don't configure it.
	Serialization RestResourceSerialization[Entity, ID]

	// Mapping is the primary Entity to DTO mapping configuration.
	Mapping dtokit.Mapper[Entity]

	// MappingForMediaType defines a per MIMEType Mapping, that takes priority over Mapping
	MappingForMediaType map[string]dtokit.Mapper[Entity]

	// ErrorHandler is used to handle errors from the request, by mapping the error value into an error DTOMapping.
	ErrorHandler ErrorHandler

	// IDContextKey is an optional field used to store the parsed ID from the URL in the context.
	//
	// Default: IDContextKey[Entity, ID]{}
	IDContextKey any

	// IDAccessor [optional] tells how to look up or set the Entity's ID.
	//
	// Default: extid.Lookup / extid.Set
	IDAccessor extid.Accessor[Entity, ID]

	// SubRoutes is an http.Handler that will receive resource-specific requests.
	// SubRoutes is optional.
	//
	// The http.Request.Context will contain the parsed ID from the request path,
	// and can be accessed with the IDContextKey.
	//
	// Example paths
	// 		/plural-resource-identifier-name/:id/sub-routes
	// 		/users/42/status
	// 		/users/42/jobs/13
	//
	// Request paths will be stripped from their prefix.
	// For example, "/users/42/jobs" will end up as "/jobs".
	SubRoutes http.Handler

	// BodyReadLimit is the max bytes that the handler is willing to read from the request body.
	//
	// The default value is DefaultBodyReadLimit, which is preset to 16MB.
	BodyReadLimit iokit.ByteSize
}

RestResource is an HTTP Handler that allows you to expose a resource such as a repository as a Restful API resource. Depending on what CRUD operation is supported by the Handler.RestResource, the Handler supports the following actions:

Example
fooRepository := memory.NewRepository[X, XID](memory.NewMemory())
fooRestfulResource := httpkit.RestResource[X, XID]{
	Create: fooRepository.Create,
	Index: func(ctx context.Context) (iterators.Iterator[X], error) { // example with query based filtering
		foos, err := fooRepository.FindAll(ctx)
		if err != nil {
			return foos, err
		}
		req, _ := httpkit.LookupRequest(ctx)
		if bt := req.URL.Query().Get("bigger"); bt != "" {
			bigger, err := strconv.Atoi(bt)
			if err != nil {
				return nil, err
			}
			foos = iterators.Filter(foos, func(foo X) bool {
				return bigger < foo.N
			})
		}

		return foos, nil
	},

	Show:    fooRepository.FindByID,
	Update:  fooRepository.Update,
	Destroy: fooRepository.DeleteByID,

	Mapping: dtokit.Mapping[X, XDTO]{},

	MappingForMediaType: map[string]dtokit.Mapper[X]{
		mediatype.JSON: dtokit.Mapping[X, XDTO]{},
	},
}

mux := http.NewServeMux()
httpkit.Mount(mux, "/foos", fooRestfulResource)

func (RestResource[Entity, ID]) ServeHTTP added in v0.220.0

func (res RestResource[Entity, ID]) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (RestResource[Entity, ID]) WithCRUD added in v0.220.0

func (res RestResource[Entity, ID]) WithCRUD(repo crud.ByIDFinder[Entity, ID]) RestResource[Entity, ID]

type RestResourceSerialization added in v0.220.0

type RestResourceSerialization[Entity, ID any] struct {
	Serializers map[string]Serializer
	IDConverter idConverter[ID]
}

type RetryRoundTripper

type RetryRoundTripper struct {
	// Transport specifies the mechanism by which individual
	// HTTP requests are made.
	//
	// Default: http.DefaultTransport
	Transport http.RoundTripper
	// RetryStrategy will be used to evaluate if a new retry attempt should be done.
	//
	// Default: retry.ExponentialBackoff
	RetryStrategy retry.Strategy[retry.FailureCount]
	// OnStatus is an [OPTIONAL] configuration field that could contain whether a certain http status code should be retried or not.
	// The RetryRoundTripper has a default behaviour about which status code can be retried, and this option can override that.
	OnStatus map[int]bool
}
Example
package main

import (
	"net/http"
	"time"

	"go.llib.dev/frameless/pkg/httpkit"
	"go.llib.dev/frameless/pkg/retry"
)

func main() {
	httpClient := http.Client{
		Transport: httpkit.RetryRoundTripper{
			RetryStrategy: retry.ExponentialBackoff{ // optional
				Timeout: 5 * time.Minute,
			},

			Transport: http.DefaultTransport, // optional

			OnStatus: map[int]bool{ // optional
				http.StatusTeapot:          true,
				http.StatusTooManyRequests: false,
			},
		},
	}

	httpClient.Get("https://go.llib.dev")
}

func (RetryRoundTripper) RoundTrip

func (rt RetryRoundTripper) RoundTrip(request *http.Request) (resp *http.Response, err error)

RoundTrip

TODO: optional waiting based on the Retry-After header

type RoundTripperFactoryFunc added in v0.216.0

type RoundTripperFactoryFunc func(next http.RoundTripper) http.RoundTripper

RoundTripperFactoryFunc is a constructor function that is meant to wrap an http.RoundTripper with given middleware. Its http.RoundTripper argument represents the next middleware http.RoundTripper in the pipeline.

type RoundTripperFunc

type RoundTripperFunc func(request *http.Request) (*http.Response, error)

func (RoundTripperFunc) RoundTrip

func (fn RoundTripperFunc) RoundTrip(request *http.Request) (*http.Response, error)

type Router added in v0.220.0

type Router struct {
	// contains filtered or unexported fields
}
Example
var router httpkit.Router

router.Namespace("/path", func(r *httpkit.Router) {
	r.Use(SampleMiddleware)

	r.Get("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusTeapot)
	}))

	r.Post("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusTeapot)
	}))

	r.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// sub route catch-all handle
	}))

	r.Resource("foo", httpkit.RestResource[Foo, FooID]{
		Mapping: dtokit.Mapping[Foo, FooDTO]{},
		Index: func(ctx context.Context) (iterators.Iterator[Foo], error) {
			foo := Foo{
				ID:  "42",
				Foo: "foo",
				Bar: "bar",
				Baz: "baz",
			}
			return iterators.Slice([]Foo{foo}), nil
		},
	})
})

router.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	// handler that catches all requests that doesn't match anything directly
}))

router.Handle("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	// /foo endpoint for all methods
}))

func NewRouter added in v0.220.0

func NewRouter(configure ...func(*Router)) *Router

func (*Router) Connect added in v0.220.0

func (router *Router) Connect(path string, handler http.Handler)
Example
var router httpkit.Router
router.Connect("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusTeapot)
}))

func (*Router) Delete added in v0.220.0

func (router *Router) Delete(path string, handler http.Handler)
Example
var router httpkit.Router
router.Delete("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusTeapot)
}))

func (*Router) Get added in v0.220.0

func (router *Router) Get(path string, handler http.Handler)
Example
var router httpkit.Router
router.Get("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusTeapot)
}))

func (*Router) Handle added in v0.220.0

func (router *Router) Handle(pattern string, handler http.Handler)

Handle registers the handler for the given pattern. If a handler already exists for pattern, Handle panics.

Example
var router httpkit.Router
var handler http.Handler

// single endpoint
router.Handle("/foo", handler)

// catch all endpoint
router.Handle("/foo/", handler)

func (*Router) Head added in v0.220.0

func (router *Router) Head(path string, handler http.Handler)
Example
var router httpkit.Router
router.Head("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusTeapot)
}))

func (*Router) Mount added in v0.220.0

func (router *Router) Mount(path string, handler http.Handler)

Mount will mount a handler to the router. Mounting a handler will make the path observed as its root point to the handler. TODO: make this true :D

func (*Router) Namespace added in v0.220.0

func (router *Router) Namespace(path string, blk func(r *Router))
Example
var router httpkit.Router
router.Namespace("/top", func(r *httpkit.Router) {
	r.Get("/sub", /* /top/sub */
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(http.StatusTeapot)
		}))

})

func (*Router) On added in v0.220.0

func (router *Router) On(method, path string, handler http.Handler)

func (*Router) Options added in v0.220.0

func (router *Router) Options(path string, handler http.Handler)

func (*Router) Patch added in v0.220.0

func (router *Router) Patch(path string, handler http.Handler)
Example
var router httpkit.Router
router.Patch("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusTeapot)
}))

func (*Router) Post added in v0.220.0

func (router *Router) Post(path string, handler http.Handler)
Example
var router httpkit.Router
router.Post("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusTeapot)
}))

func (*Router) Put added in v0.220.0

func (router *Router) Put(path string, handler http.Handler)
Example
var router httpkit.Router
router.Put("/foo", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusTeapot)
}))

func (*Router) Resource added in v0.220.0

func (router *Router) Resource(identifier string, resource resource)

Resource will register a restful resource path using the Resource handler.

Paths for Router.Resource("/users", restapi.Resource[User, UserID]):

GET 	/users
POST 	/users
GET 	/users/:id
PUT 	/users/:id
DELETE	/users/:id

func (*Router) ServeHTTP added in v0.220.0

func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*Router) Trace added in v0.220.0

func (router *Router) Trace(path string, handler http.Handler)

func (*Router) Use added in v0.220.0

func (router *Router) Use(mws ...MiddlewareFactoryFunc)

Use will instruct the router to use a given MiddlewareFactoryFunc to

type Serializer added in v0.220.0

type Serializer interface {
	codec.Codec
}

type StringID added in v0.220.0

type StringID[ID ~string] struct{}

StringID is an OldMapping tool that you can embed in your OldMapping implementation, and it will implement the ID encoding that will be used in the URL.

func (StringID[ID]) FormatID added in v0.220.0

func (m StringID[ID]) FormatID(id ID) (string, error)

func (StringID[ID]) ParseID added in v0.220.0

func (m StringID[ID]) ParseID(id string) (ID, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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