diff --git a/server/api/submit.go b/server/api/submit.go new file mode 100644 index 0000000..8f46d31 --- /dev/null +++ b/server/api/submit.go @@ -0,0 +1,58 @@ +package api + +import ( + "encoding/json" + "io" + "log/slog" + "net/http" + + "git.jmbit.de/jmb/scanfile/server/internal/database" + "git.jmbit.de/jmb/scanfile/server/internal/processing" + "git.jmbit.de/jmb/scanfile/server/internal/utils" + "github.com/spf13/viper" +) + +func SubmitRestHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Only POST allowed", http.StatusBadRequest) + return + } + + err := r.ParseMultipartForm(viper.GetInt64("web.maxfilesizemb") * 1024 * 1024) + if err != nil { + slog.Error("Error parsing form in SubmitRestHandler", "error", err) + utils.WriteJSONError(w, err.Error(), http.StatusBadRequest) + return + } + fileData, fileHeader, err := r.FormFile("file") + if err != nil { + slog.Error("Error parsing form in SubmitRestHandler", "error", err) + utils.WriteJSONError(w, err.Error(), http.StatusBadRequest) + return + } + fileBytes, err := io.ReadAll(fileData) + if err != nil { + slog.Error("Error reading file in SubmitRestHandler", "error", err) + utils.WriteJSONError(w, err.Error(), http.StatusBadRequest) + return + } + + file, err := database.CreateFile(r.Context(), fileHeader.Filename, fileBytes) + if err != nil { + slog.Error("Error saving file in SubmitRestHandler", "error", err) + utils.WriteJSONError(w, err.Error(), http.StatusInternalServerError) + return + } + err = processing.Submit(r.Context(), file.ID) + w.Header().Set("Content-Type", "application/json") + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + w.WriteHeader(http.StatusOK) + err = enc.Encode(file) + if err != nil { + slog.Error("Error creating json encoder in SubmitRestHandler", "error", err) + utils.WriteJSONError(w, err.Error(), http.StatusInternalServerError) + return + } + +} diff --git a/server/internal/server/routes.go b/server/internal/server/routes.go index 127d168..841075b 100644 --- a/server/internal/server/routes.go +++ b/server/internal/server/routes.go @@ -3,15 +3,22 @@ package server import ( "net/http" + "git.jmbit.de/jmb/scanfile/server/api" "git.jmbit.de/jmb/scanfile/server/web" ) func RegisterRoutes() *http.ServeMux { mux := http.NewServeMux() + // Web interface mux.HandleFunc("/", web.IndexWebHandler) mux.HandleFunc("/about", web.AboutWebHandler) mux.HandleFunc("/files/{uuid}", web.FileViewWebHandler) mux.HandleFunc("POST /upload", web.IndexUploadHandler) mux.Handle("/assets/", http.FileServer(http.FS(web.Files))) + + + // REST API + mux.HandleFunc("/api/v0/submit", api.SubmitRestHandler) + return mux } diff --git a/server/internal/utils/jsonError.go b/server/internal/utils/jsonError.go new file mode 100644 index 0000000..6e5fe5b --- /dev/null +++ b/server/internal/utils/jsonError.go @@ -0,0 +1,26 @@ +package utils + +import ( + "encoding/json" + "log/slog" + "net/http" +) + +type ErrorResponse struct { + Message string `json:"message"` + Code int `json:"code,omitempty"` +} + + + +func WriteJSONError(w http.ResponseWriter, message string, statusCode int) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(statusCode) + errorRes := ErrorResponse{Message: message, Code: statusCode} + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + err := enc.Encode(errorRes) // Encode and write the JSON response + if err != nil { + slog.Error("Error in WriteJSONError", "error", err) + } +}