Skip to content

alexisvisco/kcd

Repository files navigation

Coverage Status


🌠 KCD

KCD is a grandiose REST helper that wrap your shiny handler into a classic http handler. It manages all you want for building REST services.

This library is opinionated by default but customizable which mean it uses some other libraries like Chi, Logrus... KCD is modular so each pieces of the code that rely on a specific library can be changed.

🚀 QuickStart

package main

import (
	"fmt"
	"net/http"

	"github.com/go-chi/chi"
	"github.com/go-chi/chi/middleware"

	"github.com/expectedsh/kcd"
)

func main() {
	r := chi.NewRouter()
	r.Use(middleware.RequestID)

	// You can configure kcd with kcd.Config

	r.Get("/{name}", kcd.Handler(YourHttpHandler, http.StatusOK))
	//                       ^ Here the magic happen this is the only thing you need
	//                         to do. Adding kcd.Handler(your handler)
	_ = http.ListenAndServe(":3000", r)
}

// CreateCustomerInput is an example of input for an http request.
type CreateCustomerInput struct {
	Name    string   `path:"name"`                 // you can extract value from: 'path', 'query', 'header', 'ctx'
	Emails  []string `query:"emails" exploder:","` // exploder split value with the char specified
}

// CustomerOutput is the output type of your handler it contain the input for simplicity.
type CustomerOutput struct {
	Name string `json:"name"`
}

// YourHttpHandler is your http handler but in a shiny version.
// You can add *http.ResponseWriter or http.Request in params if you want.
func YourHttpHandler(in *CreateCustomerInput) (CustomerOutput, error) {
	// do some stuff here
	fmt.Printf("%+v", in)

	return CustomerOutput{Name: in.Name}, nil
}

You can test this code by using curl curl localhost:3000/supername?emails=alexis@gmail.com,remi@gmail.com

:check: Validation

KCD can validate your input by using a fork of ozzo-validation.

Your input need to implement Validatable or ValidatableWithContext.

// Validate is the function that will be called before calling your shiny handler.
func (c CreateCustomerInput) Validate() error {
	return validation.ValidateStruct(&c,
		validation.Field(&c.Name, validation.Required, validation.Length(5, 20)),
		validation.Field(&c.Emails, validation.Each(is.Email)),
	)
}

☕ Benefits

  • More readable code
  • Focus on what it matters: business code
  • No more code duplication with unmarshalling, verifying, validating, marshalling ...
  • You could have one interface for the client and server implementation

💪 Example