geezer/httpKernel.go

103 lines
2.1 KiB
Go
Raw Permalink Normal View History

2022-02-06 22:33:02 +03:00
package geezer
import (
"io"
"net/http"
"net/url"
"strings"
)
type HttpKernel struct {
2022-02-08 02:14:57 +03:00
AppKernel
2022-02-06 22:33:02 +03:00
}
func NewHttpKernel() *HttpKernel {
return &HttpKernel{
2022-02-08 02:14:57 +03:00
AppKernel: newKernel(),
2022-02-06 22:33:02 +03:00
}
}
func (s *HttpKernel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
u, err := url.ParseRequestURI(r.RequestURI)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
parts := strings.Split(strings.Trim(u.Path, "/"), "/")
if len(parts) == 0 {
w.WriteHeader(http.StatusNotFound)
return
}
name := parts[0]
id := ""
if len(parts) > 1 {
id = parts[1]
}
method := MethodFind
switch {
case r.Method == http.MethodGet && id == "":
method = MethodFind
case r.Method == http.MethodGet && id != "":
method = MethodGet
case r.Method == http.MethodPost && id == "":
method = MethodCreate
case r.Method == http.MethodPost && id != "":
method = MethodUpdate
case r.Method == http.MethodPut:
method = MethodUpdate
case r.Method == http.MethodPatch:
method = MethodPatch
case r.Method == http.MethodDelete:
method = MethodRemove
default:
w.WriteHeader(http.StatusBadRequest)
return
}
params := Params{
Path: parts,
Query: Values(u.Query()),
Headers: Values(r.Header),
Provider: "http",
}
b, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
defer r.Body.Close()
data := Data(b)
2022-02-08 02:14:57 +03:00
result, err := s.Call(ctx, method, name, id, data, params)
2022-02-06 22:33:02 +03:00
if err != nil {
if err == ErrMethodNotFound {
w.WriteHeader(http.StatusNotFound)
return
}
w.WriteHeader(http.StatusInternalServerError)
// TODO log
return
}
w.Header().Set("Content-Type", result.ContentType())
switch method {
case MethodFind, MethodGet, MethodUpdate, MethodPatch:
w.WriteHeader(http.StatusOK)
case MethodCreate:
w.WriteHeader(http.StatusCreated)
case MethodRemove:
w.WriteHeader(http.StatusNoContent)
}
if method == MethodRemove {
return
}
if err := result.Render(w); err != nil {
w.WriteHeader(http.StatusInternalServerError)
// TODO log
}
}