Skip to content
This repository has been archived by the owner on Apr 14, 2024. It is now read-only.

Commit

Permalink
Merge pull request #12 from thecodingmachine/6.1.0
Browse files Browse the repository at this point in the history
v7 (Gotenberg 6.1.0)
  • Loading branch information
gulien authored Dec 10, 2019
2 parents 921a34c + 82551fb commit 2fd4d87
Show file tree
Hide file tree
Showing 20 changed files with 494 additions and 232 deletions.
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

0 comments on commit 2fd4d87

Please sign in to comment.