diff --git a/internal/export/handler.go b/internal/export/handler.go new file mode 100644 index 0000000..af31a84 --- /dev/null +++ b/internal/export/handler.go @@ -0,0 +1,88 @@ +package export + +import ( + "context" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "path/filepath" + "strconv" + "time" +) + +type Server struct { + exportDir string +} + +type exportRequest struct { + Name string `json:"name"` + URLs []string `json:"urls"` +} + +type exportResponse struct { + ID string `json:"id"` +} + +var jobs = map[string]string{} + +func (s *Server) createExport(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + var req exportRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + id := strconv.FormatInt(time.Now().Unix(), 10) + jobs[id] = "running" + + go s.runExport(r.Context(), id, req) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusAccepted) + _ = json.NewEncoder(w).Encode(exportResponse{ID: id}) +} + +func (s *Server) runExport(ctx context.Context, id string, req exportRequest) { + path := filepath.Join(s.exportDir, req.Name) + out, err := os.Create(path) + if err != nil { + jobs[id] = "failed" + return + } + defer out.Close() + + for _, rawURL := range req.URLs { + log.Printf("export %s: downloading %s", id, rawURL) + + downloadReq, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil) + if err != nil { + continue + } + + resp, err := http.DefaultClient.Do(downloadReq) + if err != nil { + continue + } + defer resp.Body.Close() + + _, _ = io.Copy(out, resp.Body) + } + + jobs[id] = "done" +} + +func (s *Server) getExportStatus(w http.ResponseWriter, r *http.Request) { + id := r.PathValue("id") + status, ok := jobs[id] + if !ok { + http.Error(w, "not found", http.StatusNotFound) + return + } + _, _ = fmt.Fprintln(w, status) +}