package gpaste import ( "encoding/json" "io" "net/http" "github.com/go-chi/chi/v5" "github.com/google/uuid" "go.uber.org/zap" ) type HTTPServer struct { store FileStore config *ServerConfig Logger *zap.SugaredLogger http.Server } func NewHTTPServer(cfg *ServerConfig) *HTTPServer { srv := &HTTPServer{ config: cfg, Logger: zap.NewNop().Sugar(), } srv.store = NewMemoryFileStore() r := chi.NewRouter() r.Get("/", srv.HandlerIndex) r.Post("/api/file", srv.HandlerAPIFilePost) r.Get("/api/file/{id}", srv.HandlerAPIFileGet) srv.Handler = r return srv } func (s *HTTPServer) HandlerIndex(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte("index")) } func (s *HTTPServer) HandlerAPIFilePost(w http.ResponseWriter, r *http.Request) { f := &File{ ID: uuid.Must(uuid.NewRandom()).String(), Body: r.Body, } err := s.store.Store(f) if err != nil { w.WriteHeader(http.StatusInternalServerError) s.Logger.Warnw("Error storing file.", "erorr", err, "id", f.ID, "remote_addr", r.RemoteAddr) return } s.Logger.Infow("Stored file.", "id", f.ID, "remote_addr", r.RemoteAddr) var resp = struct { Message string `json:"message"` ID string `json:"id"` URL string `json:"url"` }{ Message: "OK", ID: f.ID, URL: "TODO", } w.WriteHeader(http.StatusAccepted) encoder := json.NewEncoder(w) if err := encoder.Encode(&resp); err != nil { s.Logger.Warnw("Error encoding response to client.", "error", err, "remote_addr", r.RemoteAddr) } } func (s *HTTPServer) HandlerAPIFileGet(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") if id == "" { w.WriteHeader(http.StatusBadRequest) return } f, err := s.store.Get(id) if err != nil { // TODO: LOG w.WriteHeader(http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) if _, err := io.Copy(w, f.Body); err != nil { s.Logger.Warnw("Error writing file to client.", "error", err, "remote_addr", r.RemoteAddr) } }