about summary refs log tree commit diff stats
path: root/http/handler.go
diff options
context:
space:
mode:
authorMarkus Wüstenberg2021-10-08 15:00:20 +0200
committerGitHub2021-10-08 15:00:20 +0200
commit0001b1d60942b8add6879796be7262da8db5772f (patch)
tree6dd835b94f183d0700c2aef64407b5ab8bf7a039 /http/handler.go
parent44c274483724ae6771544d805d13124b1f5fb84c (diff)
downloadgomponents-0001b1d60942b8add6879796be7262da8db5772f.tar.lz
gomponents-0001b1d60942b8add6879796be7262da8db5772f.tar.zst
gomponents-0001b1d60942b8add6879796be7262da8db5772f.zip
Add http.Adapt function (#92)
In the new package `http`, an `Adapt` function converts a `Handler` into a `http.HandlerFunc` from the `http` stdlib package.
Diffstat (limited to 'http/handler.go')
-rw-r--r--http/handler.go42
1 files changed, 42 insertions, 0 deletions
diff --git a/http/handler.go b/http/handler.go
new file mode 100644
index 0000000..9f47bff
--- /dev/null
+++ b/http/handler.go
@@ -0,0 +1,42 @@
+// Package http provides adapters to render gomponents in http handlers.
+package http
+
+import (
+	"net/http"
+
+	g "github.com/maragudk/gomponents"
+)
+
+// Handler is like http.Handler but returns a Node and an error.
+// See Adapt for how errors are translated to HTTP responses.
+type Handler = func(http.ResponseWriter, *http.Request) (g.Node, error)
+
+type errorWithStatusCode interface {
+	StatusCode() int
+}
+
+// Adapt a Handler to a http.Handlerfunc.
+// The returned Node is rendered to the ResponseWriter, in both normal and error cases.
+// If the Handler returns an error, and it implements a "StatusCode() int" method, that HTTP status code is sent
+// in the response header. Otherwise, the status code http.StatusInternalServerError (500) is used.
+func Adapt(h Handler) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		n, err := h(w, r)
+		if err != nil {
+			switch v := err.(type) {
+			case errorWithStatusCode:
+				w.WriteHeader(v.StatusCode())
+			default:
+				w.WriteHeader(http.StatusInternalServerError)
+			}
+		}
+
+		if n == nil {
+			return
+		}
+
+		if err := n.Render(w); err != nil {
+			http.Error(w, "error rendering node: "+err.Error(), http.StatusInternalServerError)
+		}
+	}
+}