- 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
go get github.com/GrayHat12/ghastly@masterpackage 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)
}
}