ep

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2020 License: MIT Imports: 8 Imported by: 0

README

ep

A miniature framework to reduce code duplication in writing HTTP endpoints

Bug: Comparing uncomparable types

server.go:3059: http: panic serving [::1]:56146: runtime error: comparing uncomparable type validator.ValidationErrors
goroutine 15 [running]:
net/http.(*conn).serve.func1(0xc000444000)
	/usr/local/go/src/net/http/server.go:1772 +0x139
panic(0x15e9ca0, 0xc000429520)
	/usr/local/go/src/runtime/panic.go:973 +0x396
github.com/advanderveer/ep.(*Response).Render(0xc0003db480, 0x161f300, 0xc000434ba0, 0x176d160, 0xc000434b80)
	/Users/adam/Projects/go/pkg/mod/github.com/advanderveer/ep@v0.0.2/response.go:155 +0x139
github.com/advanderveer/arc-assignment/endpoint.UserSignup.Handle(0xc0003db480, 0xc000281400)
	/Users/adam/Projects/go/src/github.com/advanderveer/arc-assignment/endpoint/user_signup.go:29 +0x15c
github.com/advanderveer/ep.Handler.ServeHTTP(0xc0003dac80, 0x176be80, 0x1ba4610, 0x1776920, 0xc00042a2a0, 0xc000281400)
	/Users/adam/Projects/go/pkg/mod/github.com/advanderveer/ep@v0.0.2/handler.go:20 +0xe1
github.com/gorilla/mux.(*Router).ServeHTTP(0xc00030c0c0, 0x1776920, 0xc00042a2a0, 0xc000280f00)
	/Users/adam/Projects/go/pkg/mod/github.com/gorilla/mux@v1.7.4/mux.go:210 +0xe2
net/http.serverHandler.ServeHTTP(0xc00042a1c0, 0x1776920, 0xc00042a2a0, 0xc000280f00)
	/usr/local/go/src/net/http/server.go:2807 +0xa3
net/http.(*conn).serve(0xc000444000, 0x1777da0, 0xc00041aec0)
	/usr/local/go/src/net/http/server.go:1895 +0x86c
created by net/http.(*Server).Serve
	/usr/local/go/src/net/http/server.go:2933 +0x35c

Backlog

  • MUST get kitchen example back to work
  • MUST also add HTTP language negotiation
  • MUST output.Head and input.Check are now optional
  • MUST clean up the config and make config ergonomic
  • MUST allow exec to return a InvalidInput error
  • MUST allow default configuration to be configured
  • MUST test file upload usecase
  • MUST allow (url) query decoding when request body is JSON (first decoder to implement an interface is used?)
  • MUST have an form decoding that just takes an interface to do the actual decoding
  • MUST benchmark worst case sniffing, negotiation and base overhead
  • MUST run with race checker to check for race conditions
  • MUST allow outputs to overwrite the template to use
  • MUST be able to cache output templates
  • MUST be ergonomic to have translated templates as a response, or other (error) customizations
  • MUST fully test coding package
  • MUST find an alternative for comparing error interface values in Render
  • MUST have a better way to debug unexpected error responses for development: add factories for verbose errors
  • SHOULD allow configuring defaults for endpoint config
  • SHOULD make the Config method more ergonomic to use
  • SHOULD come with build-in logging support to debug client and server errors
  • SHOULD remove progress keeping from reader
  • SHOULD handle panics in the handle, with the same error message rendering
  • SHOULD turn most of the coding tests into table tests
  • COULD provide tooling to make endpoints extremely easy to test
  • COULD provide tooling to fuzz endpoint
  • COULD add Conf constructors for different types of endpoints: Rest, Form
  • COULD make config method on endpoint optional
  • COULD move per endpoint config to where Handler is called instead
  • COULD return an error from handle as well, since that might be a common usecase
  • COULD come with a nice error page for development
  • COULD rename 'epcoding' to just 'coding'
  • COULD rename coding to something else entirely, cofusing with HTTP encoding header name
  • COULD create http request interface for easier testing
  • COULD remove reqProgress counter
  • COULD allow input.Read to return special error that prevents decoding
  • COULD allow output.Head to return special error that prevents encoding
  • COULD better test language negotiation
  • COULD support response buffering for errors that occur halway writing the response
  • COULD allow JSON encoder configuration, i.e: indentation
  • COULD be more flexible with what content get's accepted for decoding: (i.e application/vnd.api+json should match json)
  • COULD allow configuration what content-type will be written for a encoder: i.e: application/vnd.api+json
  • WONT do content-encoding negotiation, complex: https://github.com/nytimes/gziphandler
  • WONT add a H/HF method for endpoints that are just the handle/exec func

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// InvalidInput can be used explicitely to render the response as an invalid
	// input instead of an server error
	InvalidInput = errors.New("invalid input")
)

Functions

func Decoding

func Decoding(ctx context.Context) (dec epcoding.Decoding)

Decoding will return the request decoding that was determined based on request headers and MIME sniffing. This will only be empty if the server didn't configure any decodings.

func Encoding

func Encoding(ctx context.Context) (enc epcoding.Encoding)

Encoding will return the response encoding as negotiated with the client. This will only be empty if the server didn't specify any supported encodings

func Language

func Language(ctx context.Context) (s string)

Language will return the language as negotiated with the client. This will only be empty if the server didn't provide any languages

func Negotiate

func Negotiate(cfg ConfReader, req *http.Request) *http.Request

Negotiate will look at the requests' headers and set context values for encoding, decoding and language.

Types

type CheckerInput

type CheckerInput interface {
	Input
	Check() (err error)
}

CheckerInput can be implemented by Inputs to allow them to validate themselves

type Conf

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

Conf builds endpoint configuration

func New

func New() *Conf

New inits an empty configuration

func (Conf) ClientErrFactory

func (r Conf) ClientErrFactory() func(err error) Output

ClientErrFactory returns the current client error factory

func (Conf) Copy

func (c Conf) Copy() (cc *Conf)

Copy will duplicate the configuration

func (Conf) Decodings

func (c Conf) Decodings() []epcoding.Decoding

Decodings returns the configured input decodings

func (Conf) Encodings

func (c Conf) Encodings() []epcoding.Encoding

Encodings returns the configured output encodings

func (Conf) Handler

func (c Conf) Handler(ep Endpoint) *Handler

Handler will copy the configuration and make the endpoint as a handler

func (Conf) HandlerFunc

func (c Conf) HandlerFunc(epf EndpointFunc) *Handler

HandlerFunc will copy the configuration the func as a handler

func (Conf) Languages

func (c Conf) Languages() []string

Languages return the supported languages for this endpoint

func (Conf) QueryDecoder

func (c Conf) QueryDecoder() epcoding.URLValuesDecoder

QueryDecoder configures the query to be decoded into the input struct

func (Conf) ServerErrFactory

func (r Conf) ServerErrFactory() func(err error) Output

ServerErrFactory returns the configured factory for server errors

func (*Conf) SetClientErrFactory

func (r *Conf) SetClientErrFactory(f func(err error) Output) *Conf

SetClientErrFactory configures how client error outputs are created

func (*Conf) SetDecodings

func (c *Conf) SetDecodings(decs ...epcoding.Decoding) *Conf

func (*Conf) SetEncodings

func (c *Conf) SetEncodings(encs ...epcoding.Encoding) *Conf

func (*Conf) SetLanguages

func (c *Conf) SetLanguages(langs ...string) *Conf

func (*Conf) SetQueryDecoder

func (c *Conf) SetQueryDecoder(d epcoding.URLValuesDecoder) *Conf

func (*Conf) SetServerErrFactory

func (r *Conf) SetServerErrFactory(f func(err error) Output) *Conf

SetServerErrFactory configures a factory for the creation of server error outputs

func (*Conf) SetValidator

func (c *Conf) SetValidator(v Validator) *Conf

func (Conf) Validator

func (c Conf) Validator() Validator

Validator returns the configured input validator

func (*Conf) WithDecoding

func (c *Conf) WithDecoding(decs ...epcoding.Decoding) *Conf

func (*Conf) WithEncoding

func (c *Conf) WithEncoding(encs ...epcoding.Encoding) *Conf

func (*Conf) WithLanguage

func (c *Conf) WithLanguage(langs ...string) *Conf

type ConfReader

type ConfReader interface {
	Encodings() []epcoding.Encoding
	Decodings() []epcoding.Decoding
	Languages() []string
	Validator() Validator
	QueryDecoder() epcoding.URLValuesDecoder
	ClientErrFactory() func(err error) Output
	ServerErrFactory() func(err error) Output
}

type Endpoint

type Endpoint interface {
	Handle(*Response, *http.Request)
}

Endpoint can be implemented to descibe an HTTP endpoint

type EndpointFunc

type EndpointFunc func(*Response, *http.Request)

EndpointFunc implements endpoint by providng just the Handle func

func (EndpointFunc) Handle

func (f EndpointFunc) Handle(res *Response, req *http.Request)

type Handler

type Handler struct {
	*Conf
	// contains filtered or unexported fields
}

Handler handles http for certain endpoint

func (Handler) ServeHTTP

func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP allows the endpoint to serve HTTP

type HeaderOutput

type HeaderOutput interface {
	Output
	Head(http.ResponseWriter, *http.Request) error
}

HeaderOutput can be optionally implementedd by outputs to customize the response headers

type Input

type Input interface{}

Input describes what is read from a request as input to the endpoint.

type Output

type Output interface{}

An Output represents one item that results from the endpoint is will be send as the response back to the client.

type Reader

type Reader struct {
	io.Closer
	*bufio.Reader
}

Reader is a buffered reader that keeps track of the number of bytes that have been read.

func NewReader

func NewReader(r io.ReadCloser) *Reader

NewReader turns an unbuffered reader into a buffered read that keeps track of reading progress. The buffer size is 512 bytes to allow MIME sniffing of the readers content

func (*Reader) Sniff

func (r *Reader) Sniff() (ct string)

Sniff will use peek into the reader and tries to determine the content type

type ReaderInput

type ReaderInput interface {
	Input
	Read(r *http.Request) error
}

ReaderInput is an input that may optionally be implemented by inputs to indicate that it has custom logic for reading the request.

type Response

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

Response is an http.ResponseWriter implementation that comes with a host of untility method for common tasks in http handling.

func NewResponse

func NewResponse(
	wr http.ResponseWriter,
	req *http.Request,
	cfg ConfReader,
) (res *Response)

NewResponse initializes a new Response

func (*Response) Bind

func (r *Response) Bind(in Input) (ok bool)

Bind will use the negotiated decoder to populate the input.

func (*Response) Error

func (r *Response) Error() error

Error will return any server, client or validation error that was encountered while formulating the response.

func (*Response) Header

func (r *Response) Header() http.Header

Header implements the http.ResponseWriter's "Header" method

func (*Response) Render

func (r *Response) Render(out Output, err error)

Render will assert the provided error and earlier errors and provide appropriate feedback in the response. If 'err' is not the same error as returned by Validate() it will be handled as a server error.

func (*Response) Validate

func (r *Response) Validate(in Input) (verr error)

Validate will validate the input and return any error. It will first use any struct validator first before using the input's check method.

func (*Response) Write

func (r *Response) Write(b []byte) (int, error)

Write implements the http.ResponseWriter's "Write" method

func (*Response) WriteHeader

func (r *Response) WriteHeader(statusCode int)

WriteHeader implements the http.ResponseWriter's "WriteHeader" method

type Validator

type Validator interface {
	Validate(v interface{}) error
}

Validator may be implemented and configured to allow automatic validation of all endpoint inputs.

Directories

Path Synopsis
Package header provides functions for parsing HTTP headers.
Package header provides functions for parsing HTTP headers.

Jump to

Keyboard shortcuts

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