Files
2026-05-29 15:39:51 +07:00

92 lines
2.2 KiB
Go

package main
import (
"encoding/json"
"errors"
"fmt"
"net/http"
)
type mergeRequest struct {
Name string `json:"name"`
URLs []string `json:"urls"`
MergeRequestID int64 `json:"mergeRequestID"`
TOrderHeaderID int64 `json:"T_OrderHeaderID"`
}
type mergeFunc func(urls []string) ([]byte, error)
type mergeHandler struct {
secret string
merge mergeFunc
}
func newMergeHandler(secret string, merge mergeFunc) http.Handler {
return &mergeHandler{secret: secret, merge: merge}
}
func (h *mergeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeError(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
if r.Header.Get("X-Internal-Secret") != h.secret {
writeError(w, http.StatusUnauthorized, "unauthorized")
return
}
var req mergeRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "invalid request body")
return
}
if err := validateMergeRequest(&req); err != nil {
writeError(w, http.StatusUnprocessableEntity, err.Error())
return
}
pdfBytes, err := h.merge(req.URLs)
if err != nil {
var fe *fetchError
if errors.As(err, &fe) {
if fe.HTTPStatus == http.StatusNotFound {
writeError(w, http.StatusNotFound, "source PDF not found")
return
}
writeError(w, http.StatusBadGateway, "source PDF unavailable")
return
}
writeError(w, http.StatusInternalServerError, "merge failed")
return
}
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", `inline; filename="`+req.Name+`"`)
w.WriteHeader(http.StatusOK)
_, _ = w.Write(pdfBytes)
}
func validateMergeRequest(req *mergeRequest) error {
if req.Name == "" {
return fmt.Errorf("name is required")
}
if len(req.URLs) == 0 {
return fmt.Errorf("urls must not be empty")
}
if req.MergeRequestID <= 0 {
return fmt.Errorf("mergeRequestID is required")
}
if req.TOrderHeaderID <= 0 {
return fmt.Errorf("T_OrderHeaderID is required")
}
return nil
}
func writeError(w http.ResponseWriter, code int, msg string) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
_ = json.NewEncoder(w).Encode(map[string]string{"error": msg})
}