mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-08 08:32:16 +01:00
156 lines
3.6 KiB
Go
156 lines
3.6 KiB
Go
package gotenberg
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
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"
|
|
)
|
|
|
|
var (
|
|
// A3 paper size.
|
|
A3 = [2]float64{11.7, 16.5}
|
|
// A4 paper size.
|
|
A4 = [2]float64{8.27, 11.7}
|
|
// A5 paper size.
|
|
A5 = [2]float64{5.8, 8.3}
|
|
// A6 paper size.
|
|
A6 = [2]float64{4.1, 5.8}
|
|
// Letter paper size.
|
|
Letter = [2]float64{8.5, 11}
|
|
// Legal paper size.
|
|
Legal = [2]float64{8.5, 14}
|
|
// Tabloid paper size.
|
|
Tabloid = [2]float64{11, 17}
|
|
)
|
|
|
|
var (
|
|
// NoMargins removes margins.
|
|
NoMargins = [4]float64{0, 0, 0, 0}
|
|
// NormalMargins uses 1 inche margins.
|
|
NormalMargins = [4]float64{1, 1, 1, 1}
|
|
// LargeMargins uses 2 inche margins.
|
|
LargeMargins = [4]float64{2, 2, 2, 2}
|
|
)
|
|
|
|
// Client facilitates interacting with
|
|
// the Gotenberg API.
|
|
type Client struct {
|
|
Hostname string
|
|
}
|
|
|
|
// Request is a type for sending
|
|
// form values and form files to
|
|
// the Gotenberg API.
|
|
type Request interface {
|
|
validate() error
|
|
getPostURL() string
|
|
getFormValues() map[string]string
|
|
getFormFiles() map[string]string
|
|
}
|
|
|
|
// Post sends a request to the Gotenberg API
|
|
// and returns the response.
|
|
func (c *Client) Post(req Request) (*http.Response, error) {
|
|
if err := req.validate(); err != nil {
|
|
return nil, err
|
|
}
|
|
body, contentType, err := multipartForm(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
URL := fmt.Sprintf("%s%s", c.Hostname, req.getPostURL())
|
|
resp, err := http.Post(URL, contentType, body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
// Store creates the resulting PDF to given destination.
|
|
func (c *Client) Store(req Request, dest string) error {
|
|
if hasWebhook(req) {
|
|
return errors.New("cannot use Store method with a webhook")
|
|
}
|
|
resp, err := c.Post(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return writeNewFile(dest, resp.Body)
|
|
}
|
|
|
|
func hasWebhook(req Request) bool {
|
|
webhookURL, ok := req.getFormValues()[webhookURL]
|
|
if !ok {
|
|
return false
|
|
}
|
|
return webhookURL != ""
|
|
}
|
|
|
|
func writeNewFile(fpath string, in io.Reader) error {
|
|
if err := os.MkdirAll(filepath.Dir(fpath), 0755); err != nil {
|
|
return fmt.Errorf("%s: making directory for file: %v", fpath, err)
|
|
}
|
|
out, err := os.Create(fpath)
|
|
if err != nil {
|
|
return fmt.Errorf("%s: creating new file: %v", fpath, err)
|
|
}
|
|
defer out.Close()
|
|
err = out.Chmod(0644)
|
|
if err != nil && runtime.GOOS != "windows" {
|
|
return fmt.Errorf("%s: changing file mode: %v", fpath, err)
|
|
}
|
|
_, err = io.Copy(out, in)
|
|
if err != nil {
|
|
return fmt.Errorf("%s: writing file: %v", fpath, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func fileExists(name string) bool {
|
|
_, err := os.Stat(name)
|
|
return !os.IsNotExist(err)
|
|
}
|
|
|
|
func multipartForm(req Request) (*bytes.Buffer, string, error) {
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
defer writer.Close()
|
|
for filename, fpath := range req.getFormFiles() {
|
|
in, err := os.Open(fpath)
|
|
if err != nil {
|
|
return nil, "", fmt.Errorf("%s: opening file: %v", filename, err)
|
|
}
|
|
part, err := writer.CreateFormFile("files", filename)
|
|
if err != nil {
|
|
return nil, "", fmt.Errorf("%s: creating form file: %v", filename, err)
|
|
}
|
|
_, err = io.Copy(part, in)
|
|
if err != nil {
|
|
return nil, "", fmt.Errorf("%s: copying file: %v", filename, err)
|
|
}
|
|
}
|
|
for name, value := range req.getFormValues() {
|
|
if err := writer.WriteField(name, value); err != nil {
|
|
return nil, "", fmt.Errorf("%s: writting form field: %v", name, err)
|
|
}
|
|
}
|
|
return body, writer.FormDataContentType(), nil
|
|
}
|