Skip to content

Generic domain logic adaptors for HTTP handlers.

License

Notifications You must be signed in to change notification settings

dkotik/htadaptor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hyper Text Adaptors

https://pkg.go.dev/github.com/dkotik/htadaptor https://github.com/dkotik/htadaptor/actions?query=workflow:test https://coveralls.io/github/dkotik/htadaptor https://goreportcard.com/report/github.com/dkotik/htadaptor

Package htadaptor provides convenient generic domain logic adaptors for HTTP handlers. It eliminates boiler plate code, increases security by enforcing read limits and struct validation, and reduces bugs by providing a more intuitive request data parsing API than the standard library.

Why do you need this package?

An HTTP request contains at least five various sources of input that your HTTP handlers may consider: URL path, URL query, headers, cookies, and the request body. Much of the code that you have to write manually is wrestling those inputs into a struct. Willem Schots wrote an excellent explanation here. htadaptor can do all of it for you:

myHandler := htadaptor.Must(htadaptor.NewUnaryFuncAdaptor(
  // your domain function call
  func(context.Context, *myInputStruct) (*myOutputStruct, error) {
    // ... myInputStruct is passed in already validated
    // ... the fields of myInputStruct will be populated with
    // ... the contents of `request.Body` with overrides
    //     from sources below in their given order:
  },
  htadaptor.WithPathValues("slug"),           // (1) URL routing path
  htadaptor.WithQueryValues("search"),        // (2) URL query
  htadaptor.WithHeaderValues("accessToken"),  // (3) header
  htadaptor.WithCookieValues("sessionID"),    // (4) cookie
  htadaptor.WithSessionValues("role"),        // (5) session
))

The adaptors address common function signatures of domain logic calls that operate on a request struct and return a response struct with contextual awareness all the way through the call stack including the slog.Logger:

Struct Adaptor Parameter Values Return Values
UnaryFunc context, inputStruct any, error
NullaryFunc context any, error
VoidFunc context, inputStruct error

String adaptors are best when only one request value is needed:

String Adaptor Parameter Values Return Values
UnaryStringFunc context, string any, error
VoidStringFunc context, string error

Installation

go get github.com/dkotik/htadaptor@latest

Basic Usage

mux := http.NewServeMux()
mux.Handle("/api/v1/order", htadaptor.Must(
  htadaptor.NewUnaryFuncAdaptor(myService.Order),
))

See examples folder for common project uses.

Adaptor Options

Extractors

The order of extractors matters with the latter overriding the former. Request body is always processed first.

  • Path
  • Chi Path
  • Query
  • Header
  • Cookie
  • Session
  • Request properties can also be included into deserialization:
    • extract.NewMethodExtractor
    • extract.NewHostExtractor
    • extract.NewRemoteAddressExtractor
    • extract.NewUserAgentExtractor
  • Or, make your own by implementing Extractor interface.

Credits

The core idea was sparked in conversations with members of the Ardan Labs team. Package includes reflection schema decoder from Gorilla toolkit. Similar projects:

How is htadaptor different from the other generic HTTP adaptors? It is more terse due to focusing on wrapping http.Handlers from the standard library. It is expected that the REST interface will be handled separately by either an http.Mux or a helper.

About

Generic domain logic adaptors for HTTP handlers.

Resources

License

Stars

Watchers

Forks

Packages

No packages published