/goboot

goboot - Ultralight Go web framework for bootsrapping microservices

Primary LanguageGo

goboot

MIT Licence Open Source Love

Ultralight Go web framework for bootstrapping microservices. It's built on top of popular httprouter httprouter with all the necessary middlewares hooked to get you started easily.

Features

  • Easy routes setup with alice middleware chaining

    ctx := context.Background()
    panicHandler := &AppPanicHandler{}
    
    chain := alice.New(goboot.ClearHandler, goboot.LoggingHandler)
    chain.Append(goboot.RecoverHandler(ctx, panicHandler))
    
    r.Get("/", chain.ThenFunc(Index))
  • Simple and consistent controller spec. Just return goboot.Response type from the controller

     func SignUp(w http.ResponseWriter, r *http.Request) goboot.Response {
     	us := goboot.RequestBody(r).(*User)
     	
     	savedUser, err := service.SaveUser(us)
     	if err != nil {
     		return goboot.ErrorResponse(err)
     	}
     
     	return goboot.DataResponse(savedUser)
     }

    Each controller can either return an error or success API response. JSON output that is written to the client is:

    • ErrorResponse
     {
         "status" : "ERROR",
         "error"  : "<api error message>",
         "data"   : "error data, if name"
     }
    • DataResponse
     {
         "status" : "OK",
         "data"   : {"name":"Puran S", "email":"puran@myemail.com"}
     }
  • Simple JSON POST body handler marshal's your JSON request to go struct

    • Define your request data struct
    type newsArticle struct {
       ID            bson.ObjectId `json:"id"`
       Title         string        `json:"title"`
       PublishedDate string        `json:"date_published"`
    }
    • Define route
    jsonHandler := goboot.JSONBodyHandler(ctx, newsArticle{})
    r.Post("/api/v1/articles", chain.Append(jsonHandler).ThenFunc(goboot.ResponseHandler(SaveNewsArticle)))
    • POST request handler
    func SaveNewsArticle(w http.ResponseWriter, r *http.Request) goboot.Response {
      newArtcile := goboot.RequestBody(r).(*newsArticle)
          ........
    }
  • Supports API Key or JWT Auth Token for security

    • For API Key based security append the middleware APIKeyAuth chain
    apiKeyAuthC := chain.Append(goboot.APIKeyAuth(ctx, apiErrHandler))
    • For auth token based security use JWTAuthHandler
    jwtChain := chain.Append(goboot.JWTAuthHandler(ctx, apiErrHandler))

Sample API service web.go putting it all together:

package main

import (
    "github.com/narup/go"
    "net/http"
    "fmt"
)

type AppPanicHandler struct {
}

func (eh AppPanicHandler) HandleError(r *http.Request, err error) {
   //Handle panic error best suited for your application
}

func Index(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Welcome!\n")
}

func SignUp(w http.ResponseWriter, r *http.Request) goboot.Response {
   us := goboot.RequestBody(r).(*User)
   
   savedUser, err := service.SaveUser(us)
   if err != nil {
       return goboot.ErrorResponse(err)
   }
   
   return goboot.DataResponse(savedUser)
}

func handlers() *goboot.Router {
    ctx := context.Background()
    var panicHandler = &AppPanicHandler{}
  
    chain := alice.New(goboot.ClearHandler, goboot.LoggingHandler)
    chain.Append(goboot.RecoverHandler(ctx, panicHandler))

    r := goboot.DefaultRouter(ctx)
    
    //setup routes
    r.Get("/", chain.ThenFunc(Index))
    
    userJSONHandler := goboot.JSONBodyHandler(ctx, User{})
    r.Post("/api/v1/users", chain.Append(userJSONHandler).ThenFunc(goboot.ResponseHandler(SignUp)))
}

func main() {
	port := "8080"
   fmt.Printf("Starting server on port: %s.... %s \n", port)
   log.Println("Press ctrl+E to stop the server.")
   srv := &http.Server{
   	Handler:      handlers(),
   	Addr:         port,
   	ReadTimeout:  4 * time.Minute,
   	WriteTimeout: 8 * time.Minute,
   }
   if serr := srv.ListenAndServe(); serr != nil {
   	log.Fatalf("Error starting server: %s\n", serr)
   }
}