Skip to content

Latest commit

 

History

87 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hyper Text Adaptors

https://pkg.go.dev/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.

Planned features for v1.0.0 release. ↩
  • unpanic should be based on ErrorHandler
  • Add file system adaptor with decoder that can stream files.
  • Trim dependencies to zero.

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.New().AdaptFunc(
  // 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:

Struct Adaptor Parameter Values Return Values
AdaptFunc context, inputStruct any, error
AdaptNullaryFunc context any, error
AdaptVoidFunc context, inputStruct error

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

String Adaptor Parameter Values Return Values
AdaptStringFunc context, string any, error
AdaptVoidStringFunc context, string error

Many claim that the standard library interface http.ResponseWriter is entirely sufficient for writing HTTP applications. While true in principle, the general interface is a slope for many vulnerabilities. For example, developers frequently write directly to http.ResponseWriter, which sniffs the MIME content type from early response bytes, which can disable browser protections against cross-site scripting.

Installation

go get github.com/dkotik/htadaptor@latest

Basic Usage

type order struct {
	ID string
	Items []string
}

func (o *order) Validate(ctx context.Context) error {
	if len(o.Items) == 0 {
		return errors.New("empty order")
	}
	return nil
}

type orderConfirmation struct {
	ID string
}

mux := http.NewServeMux()
mux.Handle("/api/v1/order", htadaptor.Must(
  htadaptor.New().AdaptFunc(
  	func(ctx context.Context, *order) (*orderConfirmation, error) {
   		// order is provided already validated
   		// ... process order here
      return &orderConfirmation{
      	ID: order.ID,
      }, nil
   	},
  ),
))

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

Stars

23 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages