Skip to content
This repository was archived by the owner on Apr 14, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
GOLANG_VERSION=1.13
GOTENBERG_VERSION=6.0.1
GOTENBERG_VERSION=6
GOTENBERG_LOG_LEVEL=ERROR
VERSION=snapshot
GOLANGCI_LINT_VERSION=1.19.1
GOLANGCI_LINT_VERSION=1.20.1

# gofmt and goimports all go files.
fmt:
Expand All @@ -15,5 +16,5 @@ lint:

# run all tests.
tests:
docker build --build-arg GOLANG_VERSION=$(GOLANG_VERSION) --build-arg GOTENBERG_VERSION=$(GOTENBERG_VERSION) -t thecodingmachine/gotenberg-go-client:tests -f build/tests/Dockerfile .
docker build --build-arg GOLANG_VERSION=$(GOLANG_VERSION) --build-arg GOTENBERG_VERSION=$(GOTENBERG_VERSION) --build-arg GOTENBERG_LOG_LEVEL=$(GOTENBERG_LOG_LEVEL) -t thecodingmachine/gotenberg-go-client:tests -f build/tests/Dockerfile .
docker run --rm -it -v "$(PWD):/tests" thecodingmachine/gotenberg-go-client:tests
61 changes: 41 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,57 @@ A simple Go client for interacting with a Gotenberg API.
## Install

```bash
$ go get -u github.com/thecodingmachine/gotenberg-go-client/v6
$ go get -u github.com/thecodingmachine/gotenberg-go-client/v7
```

## Usage

```golang
import "github.com/thecodingmachine/gotenberg-go-client/v6"

func main() {
// HTML conversion example.
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req, _ := gotenberg.NewHTMLRequest("index.html")
req.Header("header.html")
req.Footer("footer.html")
req.Assets(
"font.woff",
"img.gif",
"style.css",
)
req.PaperSize(gotenberg.A4)
req.Margins(gotenberg.NormalMargins)
req.Landscape(false)
dest := "foo.pdf"
c.Store(req, dest)
import (
"time"
"net/http"

"github.com/thecodingmachine/gotenberg-go-client/v7"
)

// create the client.
client := &gotenberg.Client{Hostname: "http://localhost:3000"}
// ... or use your own *http.Client.
httpClient := &http.Client{
Timeout: time.Duration(5) * time.Second,
}
client := &gotenberg.Client{Hostname: "http://localhost:3000", HTTPClient: httpClient}

// prepare the files required for your conversion.

// from a path.
index, _ := gotenberg.NewDocumentFromPath("index.html", "/path/to/file")
// ... or from a string.
index, _ := gotenberg.NewDocumentFromString("index.html", "<html>Foo</html>")
// ... or from bytes.
index, _ := gotenberg.NewDocumentFromBytes("index.html", []byte("<html>Foo</html>"))

header, _ := gotenberg.NewDocumentFromPath("header.html", "/path/to/file")
footer, _ := gotenberg.NewDocumentFromPath("footer.html", "/path/to/file")
style, _ := gotenberg.NewDocumentFromPath("style.css", "/path/to/file")
img, _ := gotenberg.NewDocumentFromPath("img.png", "/path/to/file")

req := gotenberg.NewHTMLRequest(index)
req.Header(header)
req.Footer(footer)
req.Assets(style, img)
req.PaperSize(gotenberg.A4)
req.Margins(gotenberg.NoMargins)

//store method allows you to... store the resulting PDF in a particular destination.
client.Store(req, "path/you/want/the/pdf/to/be/stored.pdf")

// if you wish to redirect the response directly to the browser, you may also use:
resp, _ := client.Post(req)
```

For more complete usages, head to the [documentation](https://thecodingmachine.github.io/gotenberg).


## Badges

[![Travis CI](https://travis-ci.org/thecodingmachine/gotenberg-go-client.svg?branch=master)](https://travis-ci.org/thecodingmachine/gotenberg-go-client)
Expand Down
2 changes: 1 addition & 1 deletion build/lint/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ COPY go.sum .
# Install module dependencies.
RUN go mod download

CMD [ "golangci-lint", "run" ,"--tests=false", "--enable-all", "--disable=dupl" ]
CMD [ "golangci-lint", "run" ,"--tests=false", "--enable-all", "--disable=dupl", "--disable=wsl" ]
7 changes: 6 additions & 1 deletion build/tests/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ USER root
# | Libraries used in the build process of this image.
# |

RUN apt-get install -y git gcc
RUN apt-get update &&\
apt-get install -y git gcc

# |--------------------------------------------------------------------------
# | Golang
Expand All @@ -38,6 +39,10 @@ ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
# | Last instructions of this build.
# |

ARG GOTENBERG_LOG_LEVEL

ENV LOG_LEVEL=${GOTENBERG_LOG_LEVEL}

# Define our workding outside of $GOPATH (we're using go modules).
WORKDIR /tests

Expand Down
2 changes: 1 addition & 1 deletion build/tests/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ set -xe
# Testing Go client.
gotenberg &
sleep 10
go test -race -cover -covermode=atomic github.com/thecodingmachine/gotenberg-go-client/v6
go test -race -cover -covermode=atomic github.com/thecodingmachine/gotenberg-go-client/v7
sleep 10 # allows Gotenberg to remove generated files.
40 changes: 21 additions & 19 deletions chrome.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const (
marginLeft string = "marginLeft"
marginRight string = "marginRight"
landscapeChrome string = "landscape"
pageRanges string = "pageRanges"
googleChromeRpccBufferSize string = "googleChromeRpccBufferSize"
)

Expand Down Expand Up @@ -46,14 +47,14 @@ var (
)

type chromeRequest struct {
headerFilePath string
footerFilePath string
header Document
footer Document

*request
}

func newChromeRequest() *chromeRequest {
return &chromeRequest{"", "", newRequest()}
return &chromeRequest{nil, nil, newRequest()}
}

// WaitDelay sets waitDelay form field.
Expand All @@ -62,21 +63,13 @@ func (req *chromeRequest) WaitDelay(delay float64) {
}

// Header sets header form file.
func (req *chromeRequest) Header(fpath string) error {
if !fileExists(fpath) {
return fmt.Errorf("%s: header file does not exist", fpath)
}
req.headerFilePath = fpath
return nil
func (req *chromeRequest) Header(header Document) {
req.header = header
}

// Footer sets footer form file.
func (req *chromeRequest) Footer(fpath string) error {
if !fileExists(fpath) {
return fmt.Errorf("%s: footer file does not exist", fpath)
}
req.footerFilePath = fpath
return nil
func (req *chromeRequest) Footer(footer Document) {
req.footer = footer
}

// PaperSize sets paperWidth and paperHeight form fields.
Expand All @@ -99,14 +92,23 @@ func (req *chromeRequest) Landscape(isLandscape bool) {
req.values[landscapeChrome] = strconv.FormatBool(isLandscape)
}

// PageRanges sets pageRanges form field.
func (req *chromeRequest) PageRanges(ranges string) {
req.values[pageRanges] = ranges
}

// GoogleChromeRpccBufferSize sets googleChromeRpccBufferSize form field.
func (req *chromeRequest) GoogleChromeRpccBufferSize(bufferSize int64) {
req.values[googleChromeRpccBufferSize] = strconv.FormatInt(bufferSize, 10)
}

func (req *chromeRequest) formFiles() map[string]string {
files := make(map[string]string)
files["header.html"] = req.headerFilePath
files["footer.html"] = req.footerFilePath
func (req *chromeRequest) formFiles() map[string]Document {
files := make(map[string]Document)
if req.header != nil {
files["header.html"] = req.header
}
if req.footer != nil {
files["footer.html"] = req.footer
}
return files
}
58 changes: 40 additions & 18 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,39 @@ import (
)

const (
resultFilename string = "resultFilename"
waitTimeout string = "waitTimeout"
webhookURL string = "webhookURL"
webhookURLTimeout string = "webhookURLTimeout"
resultFilename string = "resultFilename"
waitTimeout string = "waitTimeout"
webhookURL string = "webhookURL"
webhookURLTimeout string = "webhookURLTimeout"
webhookURLBaseHTTPHeaderKey string = "Gotenberg-Webhookurl-"
)

// Client facilitates interacting with
// the Gotenberg API.
type Client struct {
Hostname string
Hostname string
HTTPClient *http.Client
}

// Request is a type for sending
// form values and form files to
// the Gotenberg API.
type Request interface {
postURL() string
customHTTPHeaders() map[string]string
formValues() map[string]string
formFiles() map[string]string
formFiles() map[string]Document
}

type request struct {
values map[string]string
httpHeaders map[string]string
values map[string]string
}

func newRequest() *request {
return &request{
values: make(map[string]string),
httpHeaders: make(map[string]string),
values: make(map[string]string),
}
}

Expand All @@ -50,7 +55,7 @@ func (req *request) ResultFilename(filename string) {
req.values[resultFilename] = filename
}

// WaitTiemout sets waitTimeout form field.
// WaitTimeout sets waitTimeout form field.
func (req *request) WaitTimeout(timeout float64) {
req.values[waitTimeout] = strconv.FormatFloat(timeout, 'f', 2, 64)
}
Expand All @@ -65,6 +70,16 @@ func (req *request) WebhookURLTimeout(timeout float64) {
req.values[webhookURLTimeout] = strconv.FormatFloat(timeout, 'f', 2, 64)
}

// AddWebhookURLHTTPHeader add a webhook custom HTTP header.
func (req *request) AddWebhookURLHTTPHeader(key, value string) {
key = fmt.Sprintf("%s%s", webhookURLBaseHTTPHeaderKey, key)
req.httpHeaders[key] = value
}

func (req *request) customHTTPHeaders() map[string]string {
return req.httpHeaders
}

func (req *request) formValues() map[string]string {
return req.values
}
Expand All @@ -76,8 +91,19 @@ func (c *Client) Post(req Request) (*http.Response, error) {
if err != nil {
return nil, err
}
if c.HTTPClient == nil {
c.HTTPClient = &http.Client{}
}
URL := fmt.Sprintf("%s%s", c.Hostname, req.postURL())
resp, err := http.Post(URL, contentType, body) /* #nosec */
httpReq, err := http.NewRequest(http.MethodPost, URL, body)
if err != nil {
return nil, err
}
httpReq.Header.Set("Content-Type", contentType)
for key, value := range req.customHTTPHeaders() {
httpReq.Header.Set(key, value)
}
resp, err := c.HTTPClient.Do(httpReq) /* #nosec */
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -138,14 +164,10 @@ func multipartForm(req Request) (*bytes.Buffer, string, error) {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
defer writer.Close() // nolint: errcheck
for filename, fpath := range req.formFiles() {
// https://github.com/thecodingmachine/gotenberg-go-client/issues/3
if fpath == "" {
continue
}
in, err := os.Open(fpath)
for filename, document := range req.formFiles() {
in, err := document.Reader()
if err != nil {
return nil, "", fmt.Errorf("%s: opening file: %v", filename, err)
return nil, "", fmt.Errorf("%s: creating reader: %v", filename, err)
}
defer in.Close() // nolint: errcheck
part, err := writer.CreateFormFile("files", filename)
Expand All @@ -154,7 +176,7 @@ func multipartForm(req Request) (*bytes.Buffer, string, error) {
}
_, err = io.Copy(part, in)
if err != nil {
return nil, "", fmt.Errorf("%s: copying file: %v", filename, err)
return nil, "", fmt.Errorf("%s: copying data: %v", filename, err)
}
}
for name, value := range req.formValues() {
Expand Down
Loading