Skip to content

GrayHat12/ghastly

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ghastly

  • Let's you plug your own state per request
  • Bare bones (fast and lightweight)
  • Support for middlewares, cancellations in the middleware, response parsing etc
  • Endpoints as services
    • you can also have multiple endpoints on the same service depending on your usecase

Installation

go get github.com/GrayHat12/ghastly@master

Example Usage

package main

import (
	"fmt"
	"log"
	"log/slog"
	"math/rand"
	"net/http"
	"time"

	"github.com/GrayHat12/ghastly"
)

type RequestState struct {
	RequestId string
	Logger    *slog.Logger
	StartTime time.Time
	EndTime   time.Time
}

func requestMiddleware(state *RequestState, response *ghastly.Response, request *http.Request, next func(*RequestState) *RequestState, cancel func(*RequestState)) *RequestState {
	state.RequestId = fmt.Sprintf("requestid-%d", rand.Int())
	state.Logger = slog.Default().With("requestid", state.RequestId)
	state.Logger.Info("at request middleware")
	return next(state)
}

func timelogMiddleware(state *RequestState, response *ghastly.Response, request *http.Request, next func(*RequestState) *RequestState, cancel func(*RequestState)) *RequestState {
	state.StartTime = time.Now()
	state.Logger.Info("at timelog middleware")
	state = next(state)
	state.Logger.Info("at timelog middleware after next")
	elapsed := time.Since(state.StartTime).Seconds()
	state.Logger.Info(fmt.Sprintf("Elapsed Time for [%s] %s is %f seconds", request.Method, request.URL, elapsed))
	return state
}

type HelloRequest struct {
	Method string
	Ip     string
}
type HelloResponse struct {
	Hello string `json:"hello"`
}

type HelloService struct {
}

func (hello HelloService) ProcessingFunction(state *RequestState, response *ghastly.Response, request *HelloRequest) *RequestState {
	state.Logger.Info("at processing")
	response.Body = HelloResponse{
		Hello: fmt.Sprintf("hello world to %s %s", request.Method, request.Ip),
	}
	return state
}

func (hello HelloService) Validator(state *RequestState, response *ghastly.Response, request *http.Request) (*RequestState, *HelloRequest, error) {
	req := HelloRequest{
		Method: request.Method,
		Ip:     request.RemoteAddr,
	}
	return state, &req, nil
}

func (hello HelloService) HandleRequest(state *RequestState, response *ghastly.Response, request *http.Request) *RequestState {
	state.Logger.Info("at service handler request")
	state, req, err := hello.Validator(state, response, request)
	if err != nil {
		state.Logger.Error("error validating hello call", "error", err)
		response.StatusCode = http.StatusBadRequest
		return state
	}
	state.Logger.Info("after service validator")
	return hello.ProcessingFunction(state, response, req)
}

func main() {

	server := ghastly.NewGhastly[RequestState](ghastly.Server{Addr: ":8090"})
	server.Get("/hello", []ghastly.Middleware[RequestState]{requestMiddleware, timelogMiddleware}, HelloService{})

	err := server.ListenAndServe()
	if err != nil {
		log.Fatal(err)
	}
}

About

golang http framework

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages