mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-08 08:32:16 +01:00
185 lines
4.9 KiB
Go
185 lines
4.9 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"github.com/labstack/echo"
|
|
"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
|
|
)
|
|
|
|
const (
|
|
webhookURL string = "webhookURL"
|
|
paperWidth string = "paperWidth"
|
|
paperHeight string = "paperHeight"
|
|
marginTop string = "marginTop"
|
|
marginBottom string = "marginBottom"
|
|
marginLeft string = "marginLeft"
|
|
marginRight string = "marginRight"
|
|
landscape string = "landscape"
|
|
)
|
|
|
|
// resource facilitates storing and accessing
|
|
// data from a multipart/form-data request.
|
|
type resource struct {
|
|
values map[string]string
|
|
dirPath string
|
|
}
|
|
|
|
func newResource(c echo.Context) (*resource, error) {
|
|
v := make(map[string]string)
|
|
v[webhookURL] = c.FormValue(webhookURL)
|
|
v[paperWidth] = c.FormValue(paperWidth)
|
|
v[paperHeight] = c.FormValue(paperHeight)
|
|
v[marginTop] = c.FormValue(marginTop)
|
|
v[marginBottom] = c.FormValue(marginBottom)
|
|
v[marginLeft] = c.FormValue(marginLeft)
|
|
v[marginRight] = c.FormValue(marginRight)
|
|
v[landscape] = c.FormValue(landscape)
|
|
dirPath, err := rand.Get()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := os.MkdirAll(dirPath, 0755); err != nil {
|
|
return nil, fmt.Errorf("%s: making directory: %v", dirPath, err)
|
|
}
|
|
r := &resource{values: v, dirPath: dirPath}
|
|
form, err := c.MultipartForm()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getting multipart form: %v", err)
|
|
}
|
|
for _, files := range form.File {
|
|
for _, fh := range files {
|
|
in, err := fh.Open()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s: opening file: %v", fh.Filename, err)
|
|
}
|
|
defer in.Close()
|
|
if err := r.writeFile(fh.Filename, in); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func (r *resource) writeFile(filename string, in io.Reader) error {
|
|
fpath := fmt.Sprintf("%s/%s", r.dirPath, filename)
|
|
out, err := os.Create(fpath)
|
|
if err != nil {
|
|
return fmt.Errorf("%s: creating new file: %v", fpath, err)
|
|
}
|
|
defer out.Close()
|
|
if err := out.Chmod(0644); err != nil {
|
|
return fmt.Errorf("%s: changing file mode: %v", fpath, err)
|
|
}
|
|
if _, err := io.Copy(out, in); err != nil {
|
|
return fmt.Errorf("%s: writing file: %v", fpath, err)
|
|
}
|
|
if _, err := out.Seek(0, 0); err != nil {
|
|
return fmt.Errorf("%s: resetting read pointer: %v", fpath, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *resource) filePath(filename string) (string, error) {
|
|
fpath := fmt.Sprintf("%s/%s", r.dirPath, filename)
|
|
_, err := os.Stat(fpath)
|
|
if os.IsNotExist(err) {
|
|
return "", fmt.Errorf("%s: file does not exist", filename)
|
|
}
|
|
absPath, err := filepath.Abs(fpath)
|
|
if err != nil {
|
|
return "", fmt.Errorf("%s: getting absolute path: %v", fpath, err)
|
|
}
|
|
return absPath, nil
|
|
}
|
|
|
|
func (r *resource) filePaths(exts []string) ([]string, error) {
|
|
var fpaths []string
|
|
err := filepath.Walk(r.dirPath, func(path string, info os.FileInfo, _ error) error {
|
|
if info.IsDir() {
|
|
return nil
|
|
}
|
|
fpath, err := r.filePath(info.Name())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, ext := range exts {
|
|
if filepath.Ext(fpath) == ext {
|
|
fpaths = append(fpaths, fpath)
|
|
return nil
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return fpaths, nil
|
|
}
|
|
|
|
func (r *resource) paperSize() ([2]float64, error) {
|
|
defaultSize := [2]float64{8.27, 11.7}
|
|
widthStr := r.values[paperWidth]
|
|
heightStr := r.values[paperHeight]
|
|
if widthStr == "" || heightStr == "" {
|
|
return defaultSize, nil
|
|
}
|
|
width, err := strconv.ParseFloat(widthStr, 64)
|
|
if err != nil {
|
|
return defaultSize, fmt.Errorf("paper width: %v", err)
|
|
}
|
|
height, err := strconv.ParseFloat(heightStr, 64)
|
|
if err != nil {
|
|
return defaultSize, fmt.Errorf("paper height: %v", err)
|
|
}
|
|
return [2]float64{width, height}, nil
|
|
}
|
|
|
|
func (r *resource) paperMargins() ([4]float64, error) {
|
|
defaultMargins := [4]float64{1, 1, 1, 1}
|
|
topStr := r.values[marginTop]
|
|
bottomStr := r.values[marginBottom]
|
|
leftStr := r.values[marginLeft]
|
|
rightStr := r.values[marginRight]
|
|
if topStr == "" || bottomStr == "" || leftStr == "" || rightStr == "" {
|
|
return defaultMargins, nil
|
|
}
|
|
top, err := strconv.ParseFloat(topStr, 64)
|
|
if err != nil {
|
|
return defaultMargins, fmt.Errorf("margin top: %v", err)
|
|
}
|
|
bottom, err := strconv.ParseFloat(bottomStr, 64)
|
|
if err != nil {
|
|
return defaultMargins, fmt.Errorf("margin bottom: %v", err)
|
|
}
|
|
left, err := strconv.ParseFloat(leftStr, 64)
|
|
if err != nil {
|
|
return defaultMargins, fmt.Errorf("margin left: %v", err)
|
|
}
|
|
right, err := strconv.ParseFloat(rightStr, 64)
|
|
if err != nil {
|
|
return defaultMargins, fmt.Errorf("margin right: %v", err)
|
|
}
|
|
return [4]float64{top, bottom, left, right}, nil
|
|
}
|
|
|
|
func (r *resource) landscape() (bool, error) {
|
|
landscapeStr := r.values[landscape]
|
|
if landscapeStr == "" {
|
|
return false, nil
|
|
}
|
|
landscape, err := strconv.ParseBool(landscapeStr)
|
|
if err != nil {
|
|
return false, fmt.Errorf("landscape: %v", err)
|
|
}
|
|
return landscape, nil
|
|
}
|
|
|
|
func (r *resource) webhookURL() string { return r.values[webhookURL] }
|
|
func (r *resource) removeAll() error { return os.RemoveAll(r.dirPath) }
|