package server import ( "encoding/json" "io" "log" "mime" "mime/multipart" "net/http" "runtime" "runtime/debug" "strings" "git.t-juice.club/torjus/minipaste/store" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" ) const Version = "v0.1.0" type Server struct { store store.Store http.Server } func NewServer(s store.Store) *Server { srv := &Server{store: s} r := chi.NewRouter() r.Use(middleware.RealIP) r.Use(middleware.Recoverer) r.Use(middleware.Logger) r.Get("/", srv.HandlerIndexGet) r.Route("/api", func(r chi.Router) { r.Get("/{id}", srv.HandlerAPIGet) r.Get("/", srv.HandlerAPIList) r.Post("/", srv.HandlerAPIPost) }) srv.Handler = r return srv } func (s *Server) HandlerIndexGet(w http.ResponseWriter, r *http.Request) { bi, ok := debug.ReadBuildInfo() if !ok { panic("not ok") } var commitHash string for i := range bi.Settings { if bi.Settings[i].Key == "vcs.revision" { commitHash = bi.Settings[i].Value } } resp := &ResponseIndex{ Name: "minipaste", Version: "v0.0.0", Commit: commitHash, GoVersion: runtime.Version(), } encoder := json.NewEncoder(w) if err := encoder.Encode(resp); err != nil { log.Panicf("Error encoding response: %s", err) } } func (s *Server) HandlerAPIPost(w http.ResponseWriter, r *http.Request) { // Check if multipart mediaType, params, err := mime.ParseMediaType(r.Header.Get("Content-Type")) if err != nil { log.Panicf("Error parsing media type: %s", err) } log.Printf("mt: %s", mediaType) if strings.HasPrefix(mediaType, "multipart/") { // Is multipart mr := multipart.NewReader(r.Body, params["boundary"]) for { p, err := mr.NextPart() if err == io.EOF { break } if err != nil { log.Fatal(err) } defer p.Close() id, err := s.store.Add(p) if err != nil { log.Panicf("Error storing file: %s", err) } log.Printf("Stored file with id %s", id) resp := &ResponseAPIPost{ID: id} encoder := json.NewEncoder(w) if err := encoder.Encode(resp); err != nil { log.Panicf("Error encoding response: %s", err) } } } else { // Is not multipart // TODO: Not working if mediaType == "application/x-www-form-urlencoded" { if err := r.ParseForm(); err != nil { log.Printf("Error parsing form: %s", err) } for key := range r.Form { file, _, err := r.FormFile(key) if err != nil { log.Panicf("Error parsing formfile: %s", err) } defer file.Close() id, err := s.store.Add(file) if err != nil { log.Panicf("Error storing file: %s", err) } log.Printf("Stored file with id %s", id) resp := &ResponseAPIPost{ID: id} encoder := json.NewEncoder(w) if err := encoder.Encode(resp); err != nil { log.Panicf("Error encoding response: %s", err) } } } } } func (s *Server) HandlerAPIGet(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") if id == "" { log.Panicf("Missing id") } reader, err := s.store.Get(id) if err != nil { log.Panicf("No such file") } defer reader.Close() if _, err := io.Copy(w, reader); err != nil { log.Panicf("Error writing to client: %s", err) } } func (s *Server) HandlerAPIList(w http.ResponseWriter, r *http.Request) { ids, err := s.store.List() if err != nil { log.Panicf("Error listing store contents: %s", err) } resp := &ResponseAPIList{IDs: ids} encoder := json.NewEncoder(w) if err := encoder.Encode(resp); err != nil { log.Panicf("Error encoding response to client: %s", err) } }