chore: custom error

This commit is contained in:
2026-03-02 22:38:28 +01:00
parent 6c1387c1cd
commit 2491d21963
19 changed files with 363 additions and 60 deletions
-20
View File
@@ -1,20 +0,0 @@
package handleimage
import (
"io"
"log/slog"
"net/http"
)
func (h *Handler) getImage(w http.ResponseWriter, r *http.Request) {
uid := r.PathValue("uid")
img, mime, err := h.img.GetImage(r.Context(), uid)
if err != nil {
slog.Error("error wile serving image", "err", err, "uid", uid)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Add("Content-Type", mime)
io.Copy(w, img)
}
@@ -1,4 +1,4 @@
package handlehome
package resthome
import (
"net/http"
@@ -1,4 +1,4 @@
package handlehome
package resthome
import (
"context"
+43
View File
@@ -0,0 +1,43 @@
package restimage
import (
"io"
"log/slog"
"net/http"
"git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/images"
"git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/handlers/restutil"
)
func (h *Handler) getImage(w http.ResponseWriter, r *http.Request) {
uid := r.PathValue("uid")
var err error
options := images.Options{}
options.Height, err = restutil.IntParam(r, "h")
if err != nil {
restutil.SendErr(w, err)
return
}
options.Width, err = restutil.IntParam(r, "w")
if err != nil {
restutil.SendErr(w, err)
return
}
options.Quality, err = restutil.IntParam(r, "q")
if err != nil {
restutil.SendErr(w, err)
return
}
img, mime, err := h.img.GetImage(r.Context(), uid, options)
if err != nil {
slog.Error("error wile serving image", "err", err, "uid", uid)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Add("Content-Type", mime)
io.Copy(w, img)
}
@@ -1,9 +1,11 @@
package handleimage
package restimage
import (
"context"
"io"
"net/http"
"git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/images"
)
type Handler struct {
@@ -20,5 +22,5 @@ func New(mux *http.ServeMux, srv imageService) *Handler {
}
type imageService interface {
GetImage(ctx context.Context, uid string) (img io.Reader, mimeType string, err error)
GetImage(ctx context.Context, uid string, options images.Options) (img io.Reader, mimeType string, err error)
}
+68
View File
@@ -0,0 +1,68 @@
package restutil
import (
"encoding/json"
"errors"
"fmt"
"log/slog"
"net/http"
)
type ErrorType string
const (
ErrorTypeUndefinded = ""
ErrorTypeValidation = "VALIDATION"
ErrorTypeNotFound = "NOT_FOUND"
ErrorTypeServerError = "SERVER_ERROR"
)
type Error struct {
Type ErrorType `json:"type"`
Message string `json:"message"`
err error
}
func WrappErr(err error, errorType ErrorType, message string) *Error {
return &Error{
Type: errorType,
Message: message,
err: err,
}
}
func (e Error) Unwrap() error {
return e.err
}
func (e Error) Error() string {
return fmt.Sprintf("%s: %s", e.Message, e.err.Error())
}
func (e Error) StatusCode() int {
switch e.Type {
case ErrorTypeValidation:
return http.StatusBadRequest
case ErrorTypeNotFound:
return http.StatusNotFound
default:
return http.StatusInternalServerError
}
}
func SendErr(w http.ResponseWriter, err error) {
restErr := &Error{}
if !errors.As(err, &restErr) {
slog.Error("internal server error", "err", err)
restErr = &Error{
Type: ErrorTypeServerError,
}
}
w.WriteHeader(restErr.StatusCode())
w.Header().Add("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(restErr)
slog.Error("could not send error", "err", err)
}
+24
View File
@@ -0,0 +1,24 @@
package restutil
import (
"fmt"
"net/http"
"strconv"
)
func IntParam(r *http.Request, key string) (val int, err error) {
str := r.URL.Query().Get(key)
if str == "" {
return
}
val, err = strconv.Atoi(str)
if err != nil {
err = WrappErr(
err,
ErrorTypeValidation,
fmt.Sprintf("failed to parse query parameter '%s': not an int", key),
)
}
return
}