ADK - Golang API Development Kit
GoDoc Reference:
Common utilities to write simple apis in golang.
- Custom API Handlers
- Custom API Request(JSON) Decoders
- Custom API URL Query-params Decoders using gorrila schema.
- App Errors
- Response Writers
Ex: Conventional way of writing api
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Post("/user", CreateUserHandler)
http.ListenAndServe(":3000", r)
}
// CreateUserHandler creates a new users
func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
reqBts, err := ioutil.ReadAll(r.Body)
if err != nil {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"error": "Couldn't read request body"}`))
return
}
var createReq createUserReq
jErr := json.Unmarshal(reqBts, &createReq)
if jErr != nil {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"error": "invalid request body"}`))
return
}
if err := validateCreateUserReq(&createReq); err != nil {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`{"error": "invalid request body"}`))
return
}
if err := store.CreateUser(&createReq); err != nil {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"error": "invalid request body"}`))
return
}
// respond to the client
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"message": "user created successfully", "id": 123}`))
}
After using custom handlers and ADK
package main
import (
"net/http"
"github.com/manigandand/adk/api"
"github.com/manigandand/adk/errors"
"github.com/manigandand/adk/middleware"
"github.com/manigandand/adk/respond"
"github.com/go-chi/chi/v5"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Method(http.MethodPost, "/user", api.Handler(CreateUserHandler))
http.ListenAndServe(":3000", r)
}
type createUserReq struct {
Email string `json:"email"`
Name string `json:"name"`
}
func (c *createUserReq) Validate() *errors.AppError {
if c.Email == "" {
return errors.KeyRequired("email")
}
return nil
}
// CreateUserHandler creates a new users
func CreateUserHandler(w http.ResponseWriter, r *http.Request) *errors.AppError{
ctx := r.Context()
var createReq createUserReq
if err := api.Decode(r, &createReq); err != nil {
return err
}
if err := store.CreateUser(&createReq); err != nil {
return err
}
// respond to the client
return respond.OK(w, map[string]interface{}{
"message": "user created successfully",
"id": 123,
})
}
NOTE:
Decoder currently will work on only on the "application/json"
body.