rpc

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Feb 23, 2025 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package rpc helps users implement [http.Handler]s using a RPC style interface.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ConsumeJsonHandler added in v0.6.0

type ConsumeJsonHandler[Req, Resp any] struct {
	// contains filtered or unexported fields
}

ConsumeJsonHandler

func ConsumeJson added in v0.6.0

func ConsumeJson[Req, Resp any](h Handler[Req, Resp]) *ConsumeJsonHandler[Req, Resp]

ConsumeJson initializes a ConsumeJsonHandler.

Example
c := ConsumerFunc[msgRequest](func(_ context.Context, req *msgRequest) error {
	fmt.Println(req.Msg)
	return nil
})

h := ConsumeJson(ReturnNothing(c))

op := NewOperation(h)

srv := httptest.NewServer(op)
defer srv.Close()

resp, err := http.Post(srv.URL, "application/json", strings.NewReader(`{"msg":"hello world"}`))
if err != nil {
	fmt.Println(err)
	return
}
if resp.StatusCode != http.StatusOK {
	fmt.Println("expected HTTP 200 status code but got", resp.StatusCode)
	return
}
if resp.Header.Get("Content-Type") != "" {
	return
}
Output:

hello world

func (*ConsumeJsonHandler[Req, Resp]) Handle added in v0.6.0

func (h *ConsumeJsonHandler[Req, Resp]) Handle(ctx context.Context, req *JsonRequest[Req]) (*Resp, error)

Handle implements the Handler interface.

type Consumer

type Consumer[T any] interface {
	Consume(context.Context, *T) error
}

Consumer consumes a request value without returning a response value.

type ConsumerFunc

type ConsumerFunc[T any] func(context.Context, *T) error

ConsumerFunc is an adapter to allow the use of ordinary functions as [Consumer]s.

func (ConsumerFunc[T]) Consume

func (c ConsumerFunc[T]) Consume(ctx context.Context, req *T) error

Consume implements the Consumer interface.

type ConsumerHandler

type ConsumerHandler[T any] struct {
	// contains filtered or unexported fields
}

ConsumerHandler is a Handler that returns a HTTP status code along with a empty response body.

This is a very handy helper for implementing HTTP POST or PUT webhook style endpoints that just consume a payload and return a status code.

func ReturnNothing

func ReturnNothing[T any](c Consumer[T]) *ConsumerHandler[T]

ReturnNothing initializes a ConsumerHandler given a Consumer.

Example
c := ConsumerFunc[msgRequest](func(_ context.Context, req *msgRequest) error {
	fmt.Println(req.Msg)
	return nil
})

h := ReturnNothing(c)

op := NewOperation(h)

srv := httptest.NewServer(op)
defer srv.Close()

resp, err := http.Post(srv.URL, "application/json", strings.NewReader(`{"msg":"hello world"}`))
if err != nil {
	fmt.Println(err)
	return
}
if resp.StatusCode != http.StatusOK {
	fmt.Println("expected HTTP 200 status code but got", resp.StatusCode)
	return
}
if resp.Header.Get("Content-Type") != "" {
	return
}
Output:

hello world

func (*ConsumerHandler[T]) Handle

func (h *ConsumerHandler[T]) Handle(ctx context.Context, req *T) (*EmptyResponse, error)

Handle implements the Handler interface.

type DuplicateStatusCodeError

type DuplicateStatusCodeError struct {
	StatusCode int
}

DuplicateStatusCodeError represents the user trying to register more than one response body spec for the same HTTP status code.

func (DuplicateStatusCodeError) Error

func (e DuplicateStatusCodeError) Error() string

Error implements the [error] interface.

type EmptyRequest

type EmptyRequest struct{}

EmptyRequest is a TypedRequest for a empty request body.

func (*EmptyRequest) ReadRequest

func (*EmptyRequest) ReadRequest(ctx context.Context, r *http.Request) error

ReadRequest implements the RequestReader interface.

func (*EmptyRequest) Spec

func (*EmptyRequest) Spec() (*openapi3.RequestBody, error)

Spec implements the TypedRequest interface.

type EmptyResponse

type EmptyResponse struct{}

EmptyResponse is a TypedResponse for a empty response body.

func (*EmptyResponse) Spec

func (*EmptyResponse) Spec() (int, *openapi3.Response, error)

Spec implements the TypedResponse interface.

func (*EmptyResponse) WriteResponse

func (*EmptyResponse) WriteResponse(ctx context.Context, w http.ResponseWriter) error

WriteResponse implements the ResponseWriter interface.

type ErrorHandler

type ErrorHandler interface {
	Handle(http.ResponseWriter, error)
}

ErrorHandler

type ErrorHandlerFunc

type ErrorHandlerFunc func(http.ResponseWriter, error)

ErrorHandlerFunc

func (ErrorHandlerFunc) Handle

func (f ErrorHandlerFunc) Handle(w http.ResponseWriter, err error)

Handle implements the ErrorHandler interface.

type Handler

type Handler[Req, Resp any] interface {
	Handle(context.Context, *Req) (*Resp, error)
}

Handler represents a RPC style implementation of the core logic for your http.Handler.

type HandlerFunc

type HandlerFunc[Req, Resp any] func(context.Context, *Req) (*Resp, error)

HandlerFunc is an adapter to allow the use of ordinary functions as [Handler]s.

func (HandlerFunc[Req, Resp]) Handle

func (f HandlerFunc[Req, Resp]) Handle(ctx context.Context, req *Req) (*Resp, error)

Handle implements the Handler interface.

type InvalidContentTypeError

type InvalidContentTypeError struct {
	ContentType string
}

InvalidContentTypeError

func (InvalidContentTypeError) Error

func (e InvalidContentTypeError) Error() string

Error implements the [error] interface.

type JsonRequest added in v0.6.0

type JsonRequest[T any] struct {
	// contains filtered or unexported fields
}

JsonRequest

func (*JsonRequest[T]) ReadRequest added in v0.6.0

func (jr *JsonRequest[T]) ReadRequest(ctx context.Context, r *http.Request) (err error)

ReadRequest implements the RequestReader interface.

func (*JsonRequest[T]) Spec added in v0.6.0

func (*JsonRequest[T]) Spec() (*openapi3.RequestBody, error)

Spec implements the TypedRequest interface.

type JsonResponse added in v0.6.0

type JsonResponse[T any] struct {
	// contains filtered or unexported fields
}

JsonResponse

func (*JsonResponse[T]) Spec added in v0.6.0

func (*JsonResponse[T]) Spec() (int, *openapi3.Response, error)

Spec implements the TypedResponse interface.

func (*JsonResponse[T]) WriteResponse added in v0.6.0

func (jr *JsonResponse[T]) WriteResponse(ctx context.Context, w http.ResponseWriter) error

WriteResponse implements the ResponseWriter interface.

type Operation

type Operation[I, O any, Req TypedRequest[I], Resp TypedResponse[O]] struct {
	// contains filtered or unexported fields
}

Operation is a http.Handler which also provides a OpenAPI 3.0 spec for itself.

func NewOperation

func NewOperation[I, O any, Req TypedRequest[I], Resp TypedResponse[O]](h Handler[I, O], opts ...OperationOption) *Operation[I, O, Req, Resp]

NewOperation initializes a Operation.

func (*Operation[I, O, Req, Resp]) ServeHTTP

func (op *Operation[I, O, Req, Resp]) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements the http.Handler interface.

func (*Operation[I, O, Req, Resp]) Spec

func (op *Operation[I, O, Req, Resp]) Spec() (openapi3.Operation, error)

Spec implements the [rest.Operation] interface.

type OperationOption

type OperationOption interface {
	ApplyOperationOption(*OperationOptions)
}

OperationOption sets a value on OperationOptions.

func OnError

func OnError(eh ErrorHandler) OperationOption

OnError

type OperationOptions

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

OperationOptions are used for configuring a Operation.

type Producer

type Producer[T any] interface {
	Produce(context.Context) (*T, error)
}

Producer returns a response value without consuming a request value.

type ProducerFunc

type ProducerFunc[T any] func(context.Context) (*T, error)

ProducerFunc is an adapter to allow the use of ordinary functions as [Producer]s.

func (ProducerFunc[T]) Produce

func (f ProducerFunc[T]) Produce(ctx context.Context) (*T, error)

Produce implements the Producer interface.

type ProducerHandler

type ProducerHandler[T any] struct {
	// contains filtered or unexported fields
}

ProducerHandler is a Handler that does not consume a request body.

This is a very handy helper for implementing HTTP GET endpoints.

func ConsumeNothing

func ConsumeNothing[T any](p Producer[T]) *ProducerHandler[T]

ConsumeNothing initializes a ProducerHandler given a Producer.

Example
p := ProducerFunc[msgResponse](func(_ context.Context) (*msgResponse, error) {
	return &msgResponse{Msg: "hello world"}, nil
})

h := ConsumeNothing(p)

op := NewOperation(h)

srv := httptest.NewServer(op)
defer srv.Close()

resp, err := http.Get(srv.URL)
if err != nil {
	fmt.Println(err)
	return
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
	fmt.Println("expected HTTP 200 status code but got", resp.StatusCode)
	return
}

contentType := resp.Header.Get("Content-Type")
if contentType != "application/json" {
	fmt.Println("expected Content-Type to be set to application/json instead of:", contentType)
	return
}

var mr msgResponse
dec := json.NewDecoder(resp.Body)
err = dec.Decode(&mr)
if err != nil {
	fmt.Println(err)
	return
}

fmt.Println(mr.Msg)
Output:

hello world

func (*ProducerHandler[T]) Handle

func (h *ProducerHandler[T]) Handle(ctx context.Context, req *EmptyRequest) (*T, error)

Handle implements the Handler interface.

type RequestReader

type RequestReader[T any] interface {
	*T

	ReadRequest(context.Context, *http.Request) error
}

RequestReader is meant to be implemented by any type which knows how unmarshal itself from a http.Request.

type ResponseWriter

type ResponseWriter[T any] interface {
	*T

	WriteResponse(context.Context, http.ResponseWriter) error
}

ResponseWriter is meant to be implemented by any type which knows how to marshal itself into a HTTP response.

type ReturnJsonHandler added in v0.6.0

type ReturnJsonHandler[Req, Resp any] struct {
	// contains filtered or unexported fields
}

ReturnJsonHandler

func ReturnJson added in v0.6.0

func ReturnJson[Req, Resp any](h Handler[Req, Resp]) *ReturnJsonHandler[Req, Resp]

ReturnJson initializes a ReturnJsonHandler.

Example
p := ProducerFunc[msgResponse](func(_ context.Context) (*msgResponse, error) {
	return &msgResponse{Msg: "hello world"}, nil
})

h := ReturnJson(ConsumeNothing(p))

op := NewOperation(h)

srv := httptest.NewServer(op)
defer srv.Close()

resp, err := http.Get(srv.URL)
if err != nil {
	fmt.Println(err)
	return
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
	fmt.Println("expected HTTP 200 status code but got", resp.StatusCode)
	return
}

contentType := resp.Header.Get("Content-Type")
if contentType != "application/json" {
	fmt.Println("expected Content-Type to be set to application/json instead of:", contentType)
	return
}

var mr msgResponse
dec := json.NewDecoder(resp.Body)
err = dec.Decode(&mr)
if err != nil {
	fmt.Println(err)
	return
}

fmt.Println(mr.Msg)
Output:

hello world

func (*ReturnJsonHandler[Req, Resp]) Handle added in v0.6.0

func (h *ReturnJsonHandler[Req, Resp]) Handle(ctx context.Context, req *Req) (*JsonResponse[Resp], error)

Handle implements the Handler interface.

type TypedRequest

type TypedRequest[T any] interface {
	RequestReader[T]

	Spec() (*openapi3.RequestBody, error)
}

TypedRequest is a RequestReader which also provides a OpenAPI 3.0 spec for itself.

type TypedResponse

type TypedResponse[T any] interface {
	ResponseWriter[T]

	Spec() (int, *openapi3.Response, error)
}

TypedResponse is a ResponseWriter which also provides a OpenAPI 3.0 spec for itself.

Jump to

Keyboard shortcuts

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