searcherside/handlers/api/v1/index_handler.go
Peter Kurfer 9ea9a8f658
Some checks failed
Go build / build (push) Failing after 1m58s
feat: continue basic setup
- setup ent scheme
- add command to create users
- document API
- add helpers to create migrations
- add command to run migrations
- add basic compose file
2024-06-19 21:19:37 +02:00

94 lines
2.6 KiB
Go

package v1
import (
"crypto/sha256"
"encoding/hex"
"io"
"mime/multipart"
"net/http"
"os"
"github.com/go-chi/chi/v5"
"code.icb4dc0.de/prskr/searcherside/core/ports"
logging2 "code.icb4dc0.de/prskr/searcherside/infrastructure/logging"
)
type IndexHandler struct {
MaxMemoryBytes int64
Indexer ports.IndexCurator
}
func (h IndexHandler) IngestIndex(writer http.ResponseWriter, req *http.Request) {
logger := logging2.GetLogger(req.Context())
if err := req.ParseMultipartForm(h.MaxMemoryBytes); err != nil {
logger.WarnContext(req.Context(), "Failed to parse multipart form", logging2.Error(err))
http.Error(writer, "Failed to parse multipart form", http.StatusInternalServerError)
return
}
if len(req.MultipartForm.File) != 1 {
http.Error(writer, "Only a single file can be uploaded", http.StatusBadRequest)
return
}
var indexFile *multipart.FileHeader
for _, files := range req.MultipartForm.File {
if len(files) != 1 {
http.Error(writer, "Only a single file can be uploaded", http.StatusBadRequest)
return
}
indexFile = files[0]
break
}
indexTempFile, err := os.CreateTemp(os.TempDir(), "searcherside-index-*")
if err != nil {
logger.ErrorContext(req.Context(), "Failed to create temporary index file", logging2.Error(err))
http.Error(writer, "Failed to create temporary index file", http.StatusInternalServerError)
return
}
hash := sha256.New()
stream, err := indexFile.Open()
if err != nil {
logger.ErrorContext(req.Context(), "Failed to open index file", logging2.Error(err))
http.Error(writer, "Failed to open index file", http.StatusBadRequest)
return
}
if _, err := io.Copy(io.MultiWriter(hash, indexTempFile), stream); err != nil {
logger.ErrorContext(req.Context(), "Failed to copy index file", logging2.Error(err))
http.Error(writer, "Failed to copy index file", http.StatusBadRequest)
return
}
if err := stream.Close(); err != nil {
logger.ErrorContext(req.Context(), "Failed to close index file", logging2.Error(err))
}
if err := indexTempFile.Close(); err != nil {
logger.ErrorContext(req.Context(), "Failed to close temporary index file", logging2.Error(err))
http.Error(writer, "Failed to close temporary index file", http.StatusInternalServerError)
return
}
go func() {
indexErr := h.Indexer.Ingest(req.Context(), ports.IngestIndexRequest{
FilePath: indexTempFile.Name(),
Hash: hex.EncodeToString(hash.Sum(nil)),
Module: chi.URLParam(req, "module"),
Instance: chi.URLParam(req, "instance"),
})
if indexErr != nil {
logger.ErrorContext(req.Context(), "Failed to ingest index", logging2.Error(indexErr))
}
}()
writer.WriteHeader(http.StatusAccepted)
}