89 lines
1.8 KiB
Go
89 lines
1.8 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
)
|
|
|
|
type ApiError struct {
|
|
Err string
|
|
Status int
|
|
}
|
|
|
|
func (e ApiError) Error() string {
|
|
return e.Err
|
|
}
|
|
|
|
type Api struct {
|
|
mux *http.ServeMux
|
|
host string
|
|
}
|
|
|
|
func NewApi(host string) Api {
|
|
return Api{
|
|
mux: http.NewServeMux(),
|
|
host: host,
|
|
}
|
|
}
|
|
|
|
func (a Api) Run() error {
|
|
log.Println("Server is running at ", a.host)
|
|
return http.ListenAndServe(a.host, a.mux)
|
|
}
|
|
|
|
func (a Api) Group(path string) group {
|
|
return group{path: path, api: &a}
|
|
}
|
|
|
|
type group struct {
|
|
api *Api
|
|
path string
|
|
}
|
|
|
|
func (g group) Group(path string) group {
|
|
p, _ := url.JoinPath(g.path, path)
|
|
return group{path: p, api: g.api}
|
|
}
|
|
|
|
type apiFunc func(http.ResponseWriter, *http.Request) error
|
|
|
|
func (g group) Endpoint(path string, f apiFunc) *group {
|
|
p, _ := url.JoinPath(g.path, path)
|
|
log.Println("New path registered: ", p, f)
|
|
g.api.mux.HandleFunc(p, func(w http.ResponseWriter, r *http.Request) {
|
|
if err := f(w, r); err != nil {
|
|
if e, ok := err.(ApiError); ok {
|
|
WriteJSON(w, e.Status, e)
|
|
return
|
|
}
|
|
WriteJSON(w, 500, ApiError{Err: err.Error(), Status: http.StatusInternalServerError})
|
|
return
|
|
}
|
|
})
|
|
return &g
|
|
}
|
|
|
|
func StatusAndContent(w http.ResponseWriter, status int, contentType string) {
|
|
w.Header().Add("Content-Type", contentType)
|
|
w.WriteHeader(status)
|
|
}
|
|
|
|
func WriteJSON(w http.ResponseWriter, status int, v any) error {
|
|
StatusAndContent(w, status, "application/json")
|
|
return json.NewEncoder(w).Encode(v)
|
|
}
|
|
|
|
func WritePlain(w http.ResponseWriter, status int, text string) error {
|
|
StatusAndContent(w, status, "text/plain")
|
|
_, err := w.Write([]byte(text))
|
|
return err
|
|
}
|
|
|
|
func WriteBlob(w http.ResponseWriter, status int, contentType string, blob []byte) error {
|
|
StatusAndContent(w, status, contentType)
|
|
_, err := w.Write(blob)
|
|
return err
|
|
}
|