minipaste/server/server.go
2022-04-20 02:37:27 +02:00

148 lines
3.1 KiB
Go

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.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
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)
}
}