From d72e2520f651fdf600c2adcc34243bcd159160df Mon Sep 17 00:00:00 2001 From: Ankit <52023083+4nkitd@users.noreply.github.com> Date: Sun, 25 Feb 2024 18:40:50 +0000 Subject: [PATCH] Added Usage Guide & facade for text/template with x-urlencoded-form decoding --- Usage.md | 56 ++++++++++++++++++++++++++++++++ facade.go | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 Usage.md create mode 100644 facade.go diff --git a/Usage.md b/Usage.md new file mode 100644 index 00000000..c27627b6 --- /dev/null +++ b/Usage.md @@ -0,0 +1,56 @@ +# Typhon Uasge Guide 🐲 + +## Installation +```bash +go get github.com/monzo/typhon +``` + +### Define Routes + +```go +router := typhon.Router{} + +router.GET("/ping", PingHandlerFun) + +router.POST("/foo", FooHandlerFun) +``` + +### Define Server & Add Middlewares +```go +svc := router.Serve(). + Filter(typhon.ErrorFilter). + Filter(typhon.H2cFilter) +``` + +### Run HTTP Server +```go +srv, err := typhon.Listen( + svc, + "localhost:8000", + typhon.WithTimeout(typhon.TimeoutOptions{Read: time.Second * 10})) + +log.Printf("👋 Listening on %v", srv.Listener().Addr()) +``` + +### Gracefully Stop Server +```go +done := make(chan os.Signal, 1) +signal.Notify(done, syscall.SIGINT, syscall.SIGTERM) +<-done +log.Printf("☠️ Shutting down") + +c, cancel := context.WithTimeout(context.Background(), 10*time.Second) +defer cancel() +srv.Stop(c) +``` + +### Define Request Handler Function +```go +func demo(req typhon.Request) typhon.Response { + appHttp := typhon.HttpFacade{Request: req} + return appHttp.ResponseWithView(200, "./demo.html", nil) +} +``` + +## Description +Typhon is a Go HTTP framework by Monzo that simplifies the process of creating robust and scalable HTTP services. This README provides instructions for installation, defining routes, setting up a server with middleware, running the server, and gracefully shutting it down. Additionally, it includes an example of defining a request handler function. \ No newline at end of file diff --git a/facade.go b/facade.go new file mode 100644 index 00000000..cff74c60 --- /dev/null +++ b/facade.go @@ -0,0 +1,97 @@ +package typhon + +package libs + +import ( + "bytes" + "html/template" + "log" + "net/url" + "strings" + + "github.com/monzo/typhon" +) + +type HttpFacade struct { + Request typhon.Request + StatusCode int + ResponseBody string +} + +func (r HttpFacade) GetFormData() map[string]string { + + requestBody, _ := r.Request.BodyBytes(false) + body := string(requestBody) + + formData := make(map[string]string) + + // Split the body string by '&' + pairs := strings.Split(body, "&") + + // Iterate over each key-value pair + for _, pair := range pairs { + // Split the pair into key and value + keyValue := strings.Split(pair, "=") + // Ensure there are exactly two parts (key and value) + if len(keyValue) == 2 { + // Decode the key-value pair and add it to the formData map + key := keyValue[0] + value := keyValue[1] + unescapedPath, err := url.PathUnescape(value) + if err != nil { + log.Println(err) + unescapedPath = value + } + formData[key] = unescapedPath + } + } + + return formData +} + +func (r HttpFacade) ResponseWithJson(statusCode int, responseBody string) typhon.Response { + + instance := typhon.NewResponse(r.Request) + instance.Writer().Header().Set("Content-Type", "application/json") + instance.Writer().Write([]byte(responseBody)) + instance.Writer().WriteHeader(statusCode) + + return instance +} + +func (r HttpFacade) ResponseWithHtml(statusCode int, responseBody string) typhon.Response { + + instance := typhon.NewResponse(r.Request) + instance.Writer().Header().Set("Content-Type", "text/html") + instance.Writer().WriteHeader(statusCode) + instance.Writer().Write([]byte(responseBody)) + + return instance +} + +func (r HttpFacade) ResponseWithView(statusCode int, viewPath string, data any) typhon.Response { + + instance := typhon.NewResponse(r.Request) + instance.Writer().Header().Set("Content-Type", "text/html") + instance.Writer().WriteHeader(statusCode) + instance.Writer().Write(r.RenderView(viewPath, data)) + + return instance +} + +func (v HttpFacade) RenderView(viewPath string, data any) []byte { + + tmpl, err := template.ParseFiles(viewPath) + ErrCheck(err, true) + + var resultHTML bytes.Buffer + err = tmpl.Execute(&resultHTML, data) + ErrCheck(err, true) + + return resultHTML.Bytes() + +} + +func (v HttpFacade) RenderViewString(viewPath string, data any) string { + return string(v.RenderView(viewPath, data)) +}