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
|
|
|
|
}
|
|
|
|
}
|