feat: updated server implementation

This commit is contained in:
David Allen 2025-08-18 11:09:51 -06:00
parent 0d27f07a8b
commit d56a9e452f
Signed by: towk
GPG key ID: 0430CDBE22619155
5 changed files with 348 additions and 75 deletions

View file

@ -3,44 +3,91 @@ package service
import (
"encoding/json"
"fmt"
"io/fs"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"git.towk2.me/towk/configurator/pkg/util"
"github.com/rs/zerolog/log"
)
func (s *Service) Download() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
path = strings.TrimPrefix(r.URL.Path, "/download")
path = s.PathForData() + strings.TrimPrefix(r.URL.Path, "/download")
fileInfo os.FileInfo
out *os.File
contents []byte
err error
)
fmt.Printf("download path: %v\n", path)
log.Debug().
Str("path", path).
Str("client_host", r.Host).
Msg("Service.Download()")
// determine if path is directory, file, or exists
if fileInfo, err = os.Stat(filepath.Clean(path)); err != nil {
if fileInfo, err = os.Stat(path); err == nil {
if fileInfo.IsDir() {
// recursively walk dir acompressednd get all filenames
// download directory as archive
out, err = os.Create(fmt.Sprintf("%s.tar", path))
if err != nil {
// create an archive of the directory and download
log.Debug().
Str("type", "directory").
Msg("Service.Download()")
archivePath := fmt.Sprintf("%d.tar.gz", time.Now().Unix())
out, err = os.Create(archivePath)
if err != nil {
s.writeErrorResponse(w, fmt.Sprintf("failed to create named file: %v", err), http.StatusInternalServerError)
return
}
err = util.CreateArchive([]string{path}, out)
if err != nil {
filesToArchive := []string{}
filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if !d.IsDir() {
filesToArchive = append(filesToArchive, path)
}
return nil
})
log.Debug().Strs("files", filesToArchive).Send()
err = util.CreateArchive(filesToArchive, out)
if err != nil {
s.writeErrorResponse(w, fmt.Sprintf("failed to create archive: %v", err.Error()), http.StatusInternalServerError)
return
}
contents, err = os.ReadFile(archivePath)
if err != nil {
s.writeErrorResponse(w, fmt.Sprintf("failed to read archive: %v", err.Error()), http.StatusInternalServerError)
return
}
w.Write(contents)
err = os.Remove(archivePath)
if err != nil {
log.Error().Err(err).Msg("failed to remove temporary archive")
return
}
} else {
// download individual file
log.Debug().
Str("type", "file").
Msg("Service.Download()")
contents, err = os.ReadFile(path)
if err != nil {
s.writeErrorResponse(w, fmt.Sprintf("failed to read file to download: %v", err.Error()), http.StatusInternalServerError)
return
}
w.Write(contents)
}
} else {
s.writeErrorResponse(w, err.Error(), http.StatusBadRequest)
return
}
}
}
@ -52,19 +99,54 @@ func (s *Service) Upload() http.HandlerFunc {
func (s *Service) List() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
path = s.PathForData() + strings.TrimPrefix(r.URL.Path, "/list")
entries []string
body []byte
err error
)
// show what we're listing
log.Debug().Str("path", path).Msg("Service.List()")
// walk directory and show all entries "ls"
err = filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
entries = append(entries, d.Name())
return nil
})
if err != nil {
switch err {
case fs.ErrNotExist, fs.ErrInvalid:
http.Error(w, "No such file or directory...", http.StatusBadRequest)
case fs.ErrPermission:
http.Error(w, "Invalid permissions...", http.StatusForbidden)
default:
http.Error(w, "Something went wrong (file or directory *probably* does not exist)...", http.StatusInternalServerError)
}
return
}
body, err = json.Marshal(entries)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(body)
}
}
func (s *Service) GetStatus(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
data := map[string]any{
"code": 200,
err := json.NewEncoder(w).Encode(map[string]any{
"code": http.StatusOK,
"message": "Configurator is healthy",
}
err := json.NewEncoder(w).Encode(data)
})
if err != nil {
fmt.Printf("failed to encode JSON: %v\n", err)
fmt.Printf("failed to encode JSON response body: %v\n", err)
return
}
}