Add auth, rest api, svelte frontend, build structure
This commit is contained in:
131
internal/api/rest.go
Normal file
131
internal/api/rest.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"git.clustercockpit.org/moebiusband/go-http-skeleton/internal/repository"
|
||||
)
|
||||
|
||||
type ErrorResponse struct {
|
||||
// Statustext of Errorcode
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"` // Error Message
|
||||
}
|
||||
|
||||
func MountApiEndpoints(r *http.ServeMux) {
|
||||
r.HandleFunc("POST /api/news/", createNewsItem)
|
||||
r.HandleFunc("GET /api/news/", readNewsItems)
|
||||
r.HandleFunc("GET /api/news/{id}", readNewsItem)
|
||||
r.HandleFunc("PATCH /api/news/", updateNewsItem)
|
||||
r.HandleFunc("DELETE /api/news/{id}", deleteNewsItem)
|
||||
}
|
||||
|
||||
func handleError(err error, statusCode int, rw http.ResponseWriter) {
|
||||
slog.Warn("rest error", "error", err)
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
rw.WriteHeader(statusCode)
|
||||
json.NewEncoder(rw).Encode(ErrorResponse{
|
||||
Status: http.StatusText(statusCode),
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
func decode(r io.Reader, val any) error {
|
||||
dec := json.NewDecoder(r)
|
||||
dec.DisallowUnknownFields()
|
||||
return dec.Decode(val)
|
||||
}
|
||||
|
||||
func createNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.CreateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.CreateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readNewsItems(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
items, err := repo.ListNews(r.Context())
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
slog.Debug("/api/news returned", "newscount", len(items))
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(items); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
item, err := repo.GetNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(item); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func updateNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.UpdateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.UpdateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func deleteNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
err = repo.DeleteNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user