diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 00f29c6c..ffa62154 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -8,7 +8,7 @@ find below useful information about how to contribute to the Gotenberg project. ### Install from sources 1. Install and run the latest version of Docker -2. Verify your Go version (>= 1.11) +2. Verify your Go version (>= 1.12) 3. Fork this repository 4. Clone it outside of your `GOPATH` (we're using Go modules) diff --git a/Makefile b/Makefile index 8cebbf3b..b259902b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -GOLANG_VERSION=1.11.2 +GOLANG_VERSION=1.12 VERSION=snapshot DOCKER_USER= DOCKER_PASSWORD= @@ -11,6 +11,7 @@ doc: # gofmt and goimports all go files. fmt: go fmt ./... + go mod tidy # run all linters. lint: diff --git a/README.md b/README.md index 98362773..344cd160 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ At TheCodingMachine, we build a lot of web applications (intranets, extranets an * Performance :zap:: Google Chrome and Libreoffice (unoconv) started once in the background thanks to PM2 * Failure prevention :broken_heart:: PM2 automatically restarts previous processes if they fail * Assets :package:: send your header, footer, images, fonts, stylesheets and so on for converting your HTML and Markdown to beaufitul PDFs! -* Easily interact with the API using our [Go](/pkg) and [PHP](https://github.com/thecodingmachine/gotenberg-php-client) libraries +* Easily interact with the API using our [Go](https://github.com/thecodingmachine/gotenberg-go-client) and [PHP](https://github.com/thecodingmachine/gotenberg-php-client) libraries ## Quick start diff --git a/build/docs/content/01-install.md b/build/docs/content/01-install.md index c9825a89..1b2b4c71 100644 --- a/build/docs/content/01-install.md +++ b/build/docs/content/01-install.md @@ -35,7 +35,7 @@ Gotenberg API is available at [http://localhost:3000](http://localhost:3000). ## Go client ```bash -$ go get -u github.com/thecodingmachine/gotenberg +$ go get -u github.com/thecodingmachine/gotenberg-go-client/v4 ``` ## PHP client diff --git a/build/docs/content/02-html.md b/build/docs/content/02-html.md index 00fc1af1..80f65d8f 100644 --- a/build/docs/content/02-html.md +++ b/build/docs/content/02-html.md @@ -206,7 +206,7 @@ $ curl --request POST \ ### Go ```golang -import "github.com/thecodingmachine/gotenberg/pkg" +import "github.com/thecodingmachine/gotenberg-go-client/v4" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} diff --git a/build/docs/content/03-url.md b/build/docs/content/03-url.md index 9342d55c..ee83767f 100644 --- a/build/docs/content/03-url.md +++ b/build/docs/content/03-url.md @@ -31,7 +31,7 @@ $ curl --request POST \ ### Go ```golang -import "github.com/thecodingmachine/gotenberg/pkg" +import "github.com/thecodingmachine/gotenberg-go-client/v4" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} diff --git a/build/docs/content/04-markdown.md b/build/docs/content/04-markdown.md index 64909bd1..cef48003 100644 --- a/build/docs/content/04-markdown.md +++ b/build/docs/content/04-markdown.md @@ -42,7 +42,7 @@ $ curl --request POST \ ### Go ```golang -import "github.com/thecodingmachine/gotenberg/pkg" +import "github.com/thecodingmachine/gotenberg-go-client/v4" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} diff --git a/build/docs/content/05-office.md b/build/docs/content/05-office.md index 697f01be..d60578b8 100644 --- a/build/docs/content/05-office.md +++ b/build/docs/content/05-office.md @@ -43,7 +43,7 @@ $ curl --request POST \ ### Go ```golang -import "github.com/thecodingmachine/gotenberg/pkg" +import "github.com/thecodingmachine/gotenberg-go-client/v4" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} diff --git a/build/docs/content/06-merge.md b/build/docs/content/06-merge.md index 1e757bca..6099a85b 100644 --- a/build/docs/content/06-merge.md +++ b/build/docs/content/06-merge.md @@ -27,7 +27,7 @@ $ curl --request POST \ ### Go ```golang -import "github.com/thecodingmachine/gotenberg/pkg" +import "github.com/thecodingmachine/gotenberg-go-client/v4" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} diff --git a/build/docs/content/07-webhook.md b/build/docs/content/07-webhook.md index ae34bbe6..ca00be45 100644 --- a/build/docs/content/07-webhook.md +++ b/build/docs/content/07-webhook.md @@ -24,7 +24,7 @@ $ curl --request POST \ ### Go ```golang -import "github.com/thecodingmachine/gotenberg/pkg" +import "github.com/thecodingmachine/gotenberg-go-client/v4" func main() { c := &gotenberg.Client{Hostname: "http://localhost:3000"} diff --git a/build/lint/Dockerfile b/build/lint/Dockerfile index aa39760c..ce0fb562 100644 --- a/build/lint/Dockerfile +++ b/build/lint/Dockerfile @@ -10,7 +10,7 @@ FROM golang:${GOLANG_VERSION}-stretch # | than gometalinter. # | -ENV GOLANGCI_LINT_VERSION 1.12.3 +ENV GOLANGCI_LINT_VERSION 1.15.0 RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b /usr/local/bin v${GOLANGCI_LINT_VERSION} &&\ golangci-lint --version diff --git a/build/tests/Dockerfile b/build/tests/Dockerfile index 0410c3eb..0c8b7c32 100644 --- a/build/tests/Dockerfile +++ b/build/tests/Dockerfile @@ -45,4 +45,4 @@ COPY go.sum . # Install module dependencies. RUN go mod download -ENTRYPOINT ["build/tests/docker-entrypoint.sh"] \ No newline at end of file +ENTRYPOINT [ "build/tests/docker-entrypoint.sh" ] \ No newline at end of file diff --git a/build/tests/docker-entrypoint.sh b/build/tests/docker-entrypoint.sh index b0e120a5..f76c5367 100755 --- a/build/tests/docker-entrypoint.sh +++ b/build/tests/docker-entrypoint.sh @@ -15,11 +15,4 @@ go test -race -cover -covermode=atomic github.com/thecodingmachine/gotenberg/int # Finally testing processes shutdown. go test github.com/thecodingmachine/gotenberg/internal/pkg/pm2 -run TestChromeShutdown -go test github.com/thecodingmachine/gotenberg/internal/pkg/pm2 -run TestUnoconvShutdown - -# Testing Go client. -go build -o /usr/local/bin/gotenberg cmd/gotenberg/main.go -gotenberg & -sleep 10 -go test -race -cover -covermode=atomic github.com/thecodingmachine/gotenberg/pkg -sleep 5 # allows Gotenberg to remove generated files (concurrent requests). \ No newline at end of file +go test github.com/thecodingmachine/gotenberg/internal/pkg/pm2 -run TestUnoconvShutdown \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index b563ab99..65fb2708 100755 --- a/docs/index.html +++ b/docs/index.html @@ -152,7 +152,7 @@ Gotenberg API is available at http://localhost:3 Go client -
$ go get -u github.com/thecodingmachine/gotenberg
+
$ go get -u github.com/thecodingmachine/gotenberg-go-client/v4
 

Go

-
import "github.com/thecodingmachine/gotenberg/pkg"
+
import "github.com/thecodingmachine/gotenberg-go-client/v4"
 
 func main() {
     c := &gotenberg.Client{Hostname: "http://localhost:3000"}
@@ -535,7 +535,7 @@ If not, some of the content of the page might be hidden.

Go -
import "github.com/thecodingmachine/gotenberg/pkg"
+
import "github.com/thecodingmachine/gotenberg-go-client/v4"
 
 func main() {
     c := &gotenberg.Client{Hostname: "http://localhost:3000"}
@@ -609,7 +609,7 @@ in the file index.html. This function will convert a given markdown
 	
 Go
 
-
import "github.com/thecodingmachine/gotenberg/pkg"
+
import "github.com/thecodingmachine/gotenberg-go-client/v4"
 
 func main() {
     c := &gotenberg.Client{Hostname: "http://localhost:3000"}
@@ -692,7 +692,7 @@ See the scalability section to find how to mitigate t
 	
 Go
 
-
import "github.com/thecodingmachine/gotenberg/pkg"
+
import "github.com/thecodingmachine/gotenberg-go-client/v4"
 
 func main() {
     c := &gotenberg.Client{Hostname: "http://localhost:3000"}
@@ -810,7 +810,7 @@ will merge them and return the resulting PDF file.

Go -
import "github.com/thecodingmachine/gotenberg/pkg"
+
import "github.com/thecodingmachine/gotenberg-go-client/v4"
 
 func main() {
     c := &gotenberg.Client{Hostname: "http://localhost:3000"}
@@ -870,7 +870,7 @@ to given URL.

Go -
import "github.com/thecodingmachine/gotenberg/pkg"
+
import "github.com/thecodingmachine/gotenberg-go-client/v4"
 
 func main() {
     c := &gotenberg.Client{Hostname: "http://localhost:3000"}
diff --git a/go.mod b/go.mod
index 8a95c99d..d3ed1ce1 100644
--- a/go.mod
+++ b/go.mod
@@ -1,5 +1,7 @@
 module github.com/thecodingmachine/gotenberg
 
+go 1.12
+
 require (
 	github.com/google/go-cmp v0.2.0 // indirect
 	github.com/gorilla/websocket v1.4.0 // indirect
diff --git a/pkg/README.md b/pkg/README.md
deleted file mode 100644
index d38f1601..00000000
--- a/pkg/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Gotenberg Go client
-
-A simple Go client for interacting with a Gotenberg API.
-
-## Install
-
-```bash
-$ go get -u github.com/thecodingmachine/gotenberg
-```
-
-## Usage
-
-```golang
-import "github.com/thecodingmachine/gotenberg/pkg"
-
-func main() {
-    // HTML conversion example.
-    c := &gotenberg.Client{Hostname: "http://localhost:3000"}
-    req, _ := gotenberg.NewHTMLRequest("index.html")
-    req.SetHeader("header.html")
-    req.SetFooter("footer.html")
-    req.SetAssets(
-        "font.woff",
-        "img.gif",
-        "style.css",
-    )
-    req.SetPaperSize(gotenberg.A4)
-    req.SetMargins(gotenberg.NormalMargins)
-    req.SetLandscape(false)
-    dest := "foo.pdf"
-    c.Store(req, dest)
-}
-```
-
-For more complete usages, head to the [documentation](https://thecodingmachine.github.io/gotenberg).
\ No newline at end of file
diff --git a/pkg/client.go b/pkg/client.go
deleted file mode 100644
index e4117878..00000000
--- a/pkg/client.go
+++ /dev/null
@@ -1,173 +0,0 @@
-package gotenberg
-
-import (
-	"bytes"
-	"errors"
-	"fmt"
-	"io"
-	"mime/multipart"
-	"net/http"
-	"os"
-	"path/filepath"
-	"runtime"
-)
-
-const (
-	remoteURL       string = "remoteURL"
-	webhookURL      string = "webhookURL"
-	paperWidth      string = "paperWidth"
-	paperHeight     string = "paperHeight"
-	marginTop       string = "marginTop"
-	marginBottom    string = "marginBottom"
-	marginLeft      string = "marginLeft"
-	marginRight     string = "marginRight"
-	landscape       string = "landscape"
-	webFontsTimeout string = "webFontsTimeout"
-)
-
-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 {
-	SetWebhookURL(webhookURL string)
-	getPostURL() string
-	getFormValues() map[string]string
-	getFormFiles() map[string]string
-}
-
-// ChromeRequest is a type for sending
-// conversion requests which will be
-// handle by Google Chrome.
-type ChromeRequest interface {
-	SetHeader(fpath string) error
-	SetFooter(fpath string) error
-	SetPaperSize(size [2]float64)
-	SetMargins(margins [4]float64)
-	SetLandscape(isLandscape bool)
-	SetWebFontsTimeout(timeout int64)
-}
-
-// UnoconvRequest is a type for sending
-// conversion requests which will be
-// handle by unoconv.
-type UnoconvRequest interface {
-	SetLandscape(landscape bool)
-}
-
-// Post sends a request to the Gotenberg API
-// and returns the response.
-func (c *Client) Post(req Request) (*http.Response, error) {
-	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: writing form field: %v", name, err)
-		}
-	}
-	return body, writer.FormDataContentType(), nil
-}
diff --git a/pkg/doc.go b/pkg/doc.go
deleted file mode 100644
index e0758176..00000000
--- a/pkg/doc.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
-Package gotenberg is a Go client for
-interacting with a Gotenberg API.
-
-For more complete usages, head to the documentation:
-https://thecodingmachine.github.io/gotenberg/
-*/
-package gotenberg
diff --git a/pkg/html.go b/pkg/html.go
deleted file mode 100644
index 39686ab0..00000000
--- a/pkg/html.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"path/filepath"
-	"strconv"
-)
-
-// HTMLRequest facilitates HTML conversion
-// with the Gotenberg API.
-type HTMLRequest struct {
-	indexFilePath  string
-	headerFilePath string
-	footerFilePath string
-	assetFilePaths []string
-	values         map[string]string
-}
-
-// NewHTMLRequest create HTMLRequest.
-func NewHTMLRequest(indexFilePath string) (*HTMLRequest, error) {
-	if !fileExists(indexFilePath) {
-		return nil, fmt.Errorf("%s: index file does not exist", indexFilePath)
-	}
-	return &HTMLRequest{indexFilePath: indexFilePath, values: make(map[string]string)}, nil
-}
-
-// SetWebhookURL sets webhookURL form field.
-func (html *HTMLRequest) SetWebhookURL(webhookURL string) {
-	html.values[webhookURL] = webhookURL
-}
-
-// SetHeader sets header form file.
-func (html *HTMLRequest) SetHeader(fpath string) error {
-	if !fileExists(fpath) {
-		return fmt.Errorf("%s: header file does not exist", fpath)
-	}
-	html.headerFilePath = fpath
-	return nil
-}
-
-// SetFooter sets footer form file.
-func (html *HTMLRequest) SetFooter(fpath string) error {
-	if !fileExists(fpath) {
-		return fmt.Errorf("%s: footer file does not exist", fpath)
-	}
-	html.footerFilePath = fpath
-	return nil
-}
-
-// SetAssets sets assets form files.
-func (html *HTMLRequest) SetAssets(fpaths ...string) error {
-	for _, fpath := range fpaths {
-		if !fileExists(fpath) {
-			return fmt.Errorf("%s: file does not exist", fpath)
-		}
-	}
-	html.assetFilePaths = fpaths
-	return nil
-}
-
-// SetPaperSize sets paperWidth and paperHeight form fields.
-func (html *HTMLRequest) SetPaperSize(size [2]float64) {
-	html.values[paperWidth] = fmt.Sprintf("%f", size[0])
-	html.values[paperHeight] = fmt.Sprintf("%f", size[1])
-}
-
-// SetMargins sets marginTop, marginBottom,
-// marginLeft and marginRight form fields.
-func (html *HTMLRequest) SetMargins(margins [4]float64) {
-	html.values[marginTop] = fmt.Sprintf("%f", margins[0])
-	html.values[marginBottom] = fmt.Sprintf("%f", margins[1])
-	html.values[marginLeft] = fmt.Sprintf("%f", margins[2])
-	html.values[marginRight] = fmt.Sprintf("%f", margins[3])
-}
-
-// SetLandscape sets landscape form field.
-func (html *HTMLRequest) SetLandscape(isLandscape bool) {
-	html.values[landscape] = strconv.FormatBool(isLandscape)
-}
-
-// SetWebFontsTimeout sets webFontsTimeout form field.
-func (html *HTMLRequest) SetWebFontsTimeout(timeout int64) {
-	html.values[webFontsTimeout] = strconv.FormatInt(timeout, 10)
-}
-
-func (html *HTMLRequest) getPostURL() string {
-	return "/convert/html"
-}
-
-func (html *HTMLRequest) getFormValues() map[string]string {
-	return html.values
-}
-
-func (html *HTMLRequest) getFormFiles() map[string]string {
-	files := make(map[string]string)
-	files["index.html"] = html.indexFilePath
-	files["header.html"] = html.headerFilePath
-	files["footer.html"] = html.footerFilePath
-	for _, fpath := range html.assetFilePaths {
-		files[filepath.Base(fpath)] = fpath
-	}
-	return files
-}
-
-// Compile-time checks to ensure type implements desired interfaces.
-var (
-	_ = Request(new(HTMLRequest))
-	_ = ChromeRequest(new(HTMLRequest))
-)
diff --git a/pkg/html_test.go b/pkg/html_test.go
deleted file mode 100644
index dc8ebe4a..00000000
--- a/pkg/html_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
-	"github.com/thecodingmachine/gotenberg/test"
-)
-
-func TestHTML(t *testing.T) {
-	c := &Client{Hostname: "http://localhost:3000"}
-	req, err := NewHTMLRequest(test.HTMLTestFilePath(t, "index.html"))
-	require.Nil(t, err)
-	err = req.SetHeader(test.HTMLTestFilePath(t, "header.html"))
-	require.Nil(t, err)
-	err = req.SetFooter(test.HTMLTestFilePath(t, "footer.html"))
-	require.Nil(t, err)
-	err = req.SetAssets(
-		test.HTMLTestFilePath(t, "font.woff"),
-		test.HTMLTestFilePath(t, "img.gif"),
-		test.HTMLTestFilePath(t, "style.css"),
-	)
-	require.Nil(t, err)
-	req.SetPaperSize(A4)
-	req.SetMargins(NormalMargins)
-	req.SetLandscape(false)
-	dirPath, err := rand.Get()
-	require.Nil(t, err)
-	dest := fmt.Sprintf("%s/foo.pdf", dirPath)
-	err = c.Store(req, dest)
-	assert.Nil(t, err)
-	assert.FileExists(t, dest)
-	err = os.RemoveAll(dirPath)
-	assert.Nil(t, err)
-}
-
-func TestConcurrentHTML(t *testing.T) {
-	for i := 0; i < 10; i++ {
-		go func() {
-			TestHTML(t)
-		}()
-	}
-}
diff --git a/pkg/markdown.go b/pkg/markdown.go
deleted file mode 100644
index 3ef045d0..00000000
--- a/pkg/markdown.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"path/filepath"
-	"strconv"
-)
-
-// MarkdownRequest facilitates Markdown conversion
-// with the Gotenberg API.
-type MarkdownRequest struct {
-	indexFilePath     string
-	markdownFilePaths []string
-	headerFilePath    string
-	footerFilePath    string
-	assetFilePaths    []string
-	values            map[string]string
-}
-
-// NewMarkdownRequest create MarkdownRequest.
-func NewMarkdownRequest(indexFilePath string, markdownFilePaths ...string) (*MarkdownRequest, error) {
-	if !fileExists(indexFilePath) {
-		return nil, fmt.Errorf("%s: index file does not exist", indexFilePath)
-	}
-	for _, fpath := range markdownFilePaths {
-		if !fileExists(fpath) {
-			return nil, fmt.Errorf("%s: markdown file does not exist", fpath)
-		}
-	}
-	return &MarkdownRequest{
-		indexFilePath:     indexFilePath,
-		markdownFilePaths: markdownFilePaths,
-		values:            make(map[string]string),
-	}, nil
-}
-
-// SetWebhookURL sets webhookURL form field.
-func (markdown *MarkdownRequest) SetWebhookURL(webhookURL string) {
-	markdown.values[webhookURL] = webhookURL
-}
-
-// SetHeader sets header form file.
-func (markdown *MarkdownRequest) SetHeader(fpath string) error {
-	if !fileExists(fpath) {
-		return fmt.Errorf("%s: header file does not exist", fpath)
-	}
-	markdown.headerFilePath = fpath
-	return nil
-}
-
-// SetFooter sets footer form file.
-func (markdown *MarkdownRequest) SetFooter(fpath string) error {
-	if !fileExists(fpath) {
-		return fmt.Errorf("%s: footer file does not exist", fpath)
-	}
-	markdown.footerFilePath = fpath
-	return nil
-}
-
-// SetAssets sets assets form files.
-func (markdown *MarkdownRequest) SetAssets(fpaths ...string) error {
-	for _, fpath := range fpaths {
-		if !fileExists(fpath) {
-			return fmt.Errorf("%s: file does not exist", fpath)
-		}
-	}
-	markdown.assetFilePaths = fpaths
-	return nil
-}
-
-// SetPaperSize sets paperWidth and paperHeight form fields.
-func (markdown *MarkdownRequest) SetPaperSize(size [2]float64) {
-	markdown.values[paperWidth] = fmt.Sprintf("%f", size[0])
-	markdown.values[paperHeight] = fmt.Sprintf("%f", size[1])
-}
-
-// SetMargins sets marginTop, marginBottom,
-// marginLeft and marginRight form fields.
-func (markdown *MarkdownRequest) SetMargins(margins [4]float64) {
-	markdown.values[marginTop] = fmt.Sprintf("%f", margins[0])
-	markdown.values[marginBottom] = fmt.Sprintf("%f", margins[1])
-	markdown.values[marginLeft] = fmt.Sprintf("%f", margins[2])
-	markdown.values[marginRight] = fmt.Sprintf("%f", margins[3])
-}
-
-// SetLandscape sets landscape form field.
-func (markdown *MarkdownRequest) SetLandscape(isLandscape bool) {
-	markdown.values[landscape] = strconv.FormatBool(isLandscape)
-}
-
-// SetWebFontsTimeout sets webFontsTimeout form field.
-func (markdown *MarkdownRequest) SetWebFontsTimeout(timeout int64) {
-	markdown.values[webFontsTimeout] = strconv.FormatInt(timeout, 10)
-}
-
-func (markdown *MarkdownRequest) getPostURL() string {
-	return "/convert/markdown"
-}
-
-func (markdown *MarkdownRequest) getFormValues() map[string]string {
-	return markdown.values
-}
-
-func (markdown *MarkdownRequest) getFormFiles() map[string]string {
-	files := make(map[string]string)
-	files["index.html"] = markdown.indexFilePath
-	files["header.html"] = markdown.headerFilePath
-	files["footer.html"] = markdown.footerFilePath
-	for _, fpath := range markdown.markdownFilePaths {
-		files[filepath.Base(fpath)] = fpath
-	}
-	for _, fpath := range markdown.assetFilePaths {
-		files[filepath.Base(fpath)] = fpath
-	}
-	return files
-}
-
-// Compile-time checks to ensure type implements desired interfaces.
-var (
-	_ = Request(new(MarkdownRequest))
-	_ = ChromeRequest(new(MarkdownRequest))
-)
diff --git a/pkg/markdown_test.go b/pkg/markdown_test.go
deleted file mode 100644
index 8e55f4eb..00000000
--- a/pkg/markdown_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
-	"github.com/thecodingmachine/gotenberg/test"
-)
-
-func TestMarkdown(t *testing.T) {
-	c := &Client{Hostname: "http://localhost:3000"}
-	req, err := NewMarkdownRequest(
-		test.MarkdownTestFilePath(t, "index.html"),
-		test.MarkdownTestFilePath(t, "paragraph1.md"),
-		test.MarkdownTestFilePath(t, "paragraph2.md"),
-		test.MarkdownTestFilePath(t, "paragraph3.md"),
-	)
-	require.Nil(t, err)
-	err = req.SetHeader(test.MarkdownTestFilePath(t, "header.html"))
-	require.Nil(t, err)
-	err = req.SetFooter(test.MarkdownTestFilePath(t, "footer.html"))
-	require.Nil(t, err)
-	err = req.SetAssets(
-		test.MarkdownTestFilePath(t, "font.woff"),
-		test.MarkdownTestFilePath(t, "img.gif"),
-		test.MarkdownTestFilePath(t, "style.css"),
-	)
-	require.Nil(t, err)
-	req.SetPaperSize(A4)
-	req.SetMargins(NormalMargins)
-	req.SetLandscape(false)
-	dirPath, err := rand.Get()
-	require.Nil(t, err)
-	dest := fmt.Sprintf("%s/foo.pdf", dirPath)
-	err = c.Store(req, dest)
-	assert.Nil(t, err)
-	assert.FileExists(t, dest)
-	err = os.RemoveAll(dirPath)
-	assert.Nil(t, err)
-}
-
-func TestConcurrentMarkdown(t *testing.T) {
-	for i := 0; i < 10; i++ {
-		go func() {
-			TestMarkdown(t)
-		}()
-	}
-}
diff --git a/pkg/merge.go b/pkg/merge.go
deleted file mode 100644
index 9b5d8546..00000000
--- a/pkg/merge.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"path/filepath"
-)
-
-// MergeRequest facilitates merging PDF
-// with the Gotenberg API.
-type MergeRequest struct {
-	filePaths []string
-	values    map[string]string
-}
-
-// NewMergeRequest create MergeRequest.
-func NewMergeRequest(fpaths ...string) (*MergeRequest, error) {
-	for _, fpath := range fpaths {
-		if !fileExists(fpath) {
-			return nil, fmt.Errorf("%s: file does not exist", fpath)
-		}
-	}
-	return &MergeRequest{filePaths: fpaths, values: make(map[string]string)}, nil
-}
-
-// SetWebhookURL sets webhookURL form field.
-func (merge *MergeRequest) SetWebhookURL(webhookURL string) {
-	merge.values[webhookURL] = webhookURL
-}
-
-func (merge *MergeRequest) getPostURL() string {
-	return "/merge"
-}
-
-func (merge *MergeRequest) getFormValues() map[string]string {
-	return merge.values
-}
-
-func (merge *MergeRequest) getFormFiles() map[string]string {
-	files := make(map[string]string)
-	for _, fpath := range merge.filePaths {
-		files[filepath.Base(fpath)] = fpath
-	}
-	return files
-}
-
-// Compile-time checks to ensure type implements desired interfaces.
-var (
-	_ = Request(new(MergeRequest))
-)
diff --git a/pkg/merge_test.go b/pkg/merge_test.go
deleted file mode 100644
index 11b408c9..00000000
--- a/pkg/merge_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
-	"github.com/thecodingmachine/gotenberg/test"
-)
-
-func TestMerge(t *testing.T) {
-	c := &Client{Hostname: "http://localhost:3000"}
-	req, err := NewMergeRequest(
-		test.PDFTestFilePath(t, "gotenberg.pdf"),
-		test.PDFTestFilePath(t, "gotenberg.pdf"),
-	)
-	require.Nil(t, err)
-	dirPath, err := rand.Get()
-	require.Nil(t, err)
-	dest := fmt.Sprintf("%s/foo.pdf", dirPath)
-	err = c.Store(req, dest)
-	assert.Nil(t, err)
-	assert.FileExists(t, dest)
-	err = os.RemoveAll(dirPath)
-	assert.Nil(t, err)
-}
-
-func TestConcurrentMerge(t *testing.T) {
-	for i := 0; i < 10; i++ {
-		go func() {
-			TestMerge(t)
-		}()
-	}
-}
diff --git a/pkg/office.go b/pkg/office.go
deleted file mode 100644
index 14e6b248..00000000
--- a/pkg/office.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"path/filepath"
-	"strconv"
-)
-
-// OfficeRequest facilitates Office documents
-// conversion with the Gotenberg API.
-type OfficeRequest struct {
-	filePaths []string
-	values    map[string]string
-}
-
-// NewOfficeRequest create OfficeRequest.
-func NewOfficeRequest(fpaths ...string) (*OfficeRequest, error) {
-	for _, fpath := range fpaths {
-		if !fileExists(fpath) {
-			return nil, fmt.Errorf("%s: file does not exist", fpath)
-		}
-	}
-	return &OfficeRequest{filePaths: fpaths, values: make(map[string]string)}, nil
-}
-
-// SetWebhookURL sets webhookURL form field.
-func (office *OfficeRequest) SetWebhookURL(webhookURL string) {
-	office.values[webhookURL] = webhookURL
-}
-
-// SetLandscape sets landscape form field.
-func (office *OfficeRequest) SetLandscape(isLandscape bool) {
-	office.values[landscape] = strconv.FormatBool(isLandscape)
-}
-
-func (office *OfficeRequest) getPostURL() string {
-	return "/convert/office"
-}
-
-func (office *OfficeRequest) getFormValues() map[string]string {
-	return office.values
-}
-
-func (office *OfficeRequest) getFormFiles() map[string]string {
-	files := make(map[string]string)
-	for _, fpath := range office.filePaths {
-		files[filepath.Base(fpath)] = fpath
-	}
-	return files
-}
-
-// Compile-time checks to ensure type implements desired interfaces.
-var (
-	_ = Request(new(OfficeRequest))
-	_ = UnoconvRequest(new(OfficeRequest))
-)
diff --git a/pkg/office_test.go b/pkg/office_test.go
deleted file mode 100644
index 938b0fe9..00000000
--- a/pkg/office_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
-	"github.com/thecodingmachine/gotenberg/test"
-)
-
-func TestOffice(t *testing.T) {
-	c := &Client{Hostname: "http://localhost:3000"}
-	req, err := NewOfficeRequest(test.OfficeTestFilePath(t, "document.docx"))
-	require.Nil(t, err)
-	req.SetLandscape(false)
-	dirPath, err := rand.Get()
-	require.Nil(t, err)
-	dest := fmt.Sprintf("%s/foo.pdf", dirPath)
-	err = c.Store(req, dest)
-	assert.Nil(t, err)
-	assert.FileExists(t, dest)
-	err = os.RemoveAll(dirPath)
-	assert.Nil(t, err)
-}
-
-func TestConcurrentOffice(t *testing.T) {
-	for i := 0; i < 10; i++ {
-		go func() {
-			TestOffice(t)
-		}()
-	}
-}
diff --git a/pkg/url.go b/pkg/url.go
deleted file mode 100644
index 9d15f780..00000000
--- a/pkg/url.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"strconv"
-)
-
-// URLRequest facilitates remote URL conversion
-// with the Gotenberg API.
-type URLRequest struct {
-	headerFilePath string
-	footerFilePath string
-	values         map[string]string
-}
-
-// NewURLRequest create URLRequest.
-func NewURLRequest(URL string) *URLRequest {
-	req := &URLRequest{values: make(map[string]string)}
-	req.values[remoteURL] = URL
-	return req
-}
-
-// SetWebhookURL sets webhookURL form field.
-func (url *URLRequest) SetWebhookURL(webhookURL string) {
-	url.values[webhookURL] = webhookURL
-}
-
-// SetHeader sets header form file.
-func (url *URLRequest) SetHeader(fpath string) error {
-	if !fileExists(fpath) {
-		return fmt.Errorf("%s: header file does not exist", fpath)
-	}
-	url.headerFilePath = fpath
-	return nil
-}
-
-// SetFooter sets footer form file.
-func (url *URLRequest) SetFooter(fpath string) error {
-	if !fileExists(fpath) {
-		return fmt.Errorf("%s: footer file does not exist", fpath)
-	}
-	url.footerFilePath = fpath
-	return nil
-}
-
-// SetPaperSize sets paperWidth and paperHeight form fields.
-func (url *URLRequest) SetPaperSize(size [2]float64) {
-	url.values[paperWidth] = fmt.Sprintf("%f", size[0])
-	url.values[paperHeight] = fmt.Sprintf("%f", size[1])
-}
-
-// SetMargins sets marginTop, marginBottom,
-// marginLeft and marginRight form fields.
-func (url *URLRequest) SetMargins(margins [4]float64) {
-	url.values[marginTop] = fmt.Sprintf("%f", margins[0])
-	url.values[marginBottom] = fmt.Sprintf("%f", margins[1])
-	url.values[marginLeft] = fmt.Sprintf("%f", margins[2])
-	url.values[marginRight] = fmt.Sprintf("%f", margins[3])
-}
-
-// SetLandscape sets landscape form field.
-func (url *URLRequest) SetLandscape(isLandscape bool) {
-	url.values[landscape] = strconv.FormatBool(isLandscape)
-}
-
-// SetWebFontsTimeout sets webFontsTimeout form field.
-func (url *URLRequest) SetWebFontsTimeout(timeout int64) {
-	url.values[webFontsTimeout] = strconv.FormatInt(timeout, 10)
-}
-
-func (url *URLRequest) getPostURL() string {
-	return "/convert/url"
-}
-
-func (url *URLRequest) getFormValues() map[string]string {
-	return url.values
-}
-
-func (url *URLRequest) getFormFiles() map[string]string {
-	files := make(map[string]string)
-	files["header.html"] = url.headerFilePath
-	files["footer.html"] = url.footerFilePath
-	return files
-}
-
-// Compile-time checks to ensure type implements desired interfaces.
-var (
-	_ = Request(new(URLRequest))
-	_ = ChromeRequest(new(URLRequest))
-)
diff --git a/pkg/url_test.go b/pkg/url_test.go
deleted file mode 100644
index 8e3fe641..00000000
--- a/pkg/url_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package gotenberg
-
-import (
-	"fmt"
-	"os"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
-	"github.com/thecodingmachine/gotenberg/test"
-)
-
-func TestURL(t *testing.T) {
-	c := &Client{Hostname: "http://localhost:3000"}
-	req := NewURLRequest("http://google.com")
-	err := req.SetHeader(test.URLTestFilePath(t, "header.html"))
-	require.Nil(t, err)
-	err = req.SetFooter(test.URLTestFilePath(t, "footer.html"))
-	require.Nil(t, err)
-	require.Nil(t, err)
-	req.SetPaperSize(A4)
-	req.SetMargins(NormalMargins)
-	req.SetLandscape(false)
-	dirPath, err := rand.Get()
-	require.Nil(t, err)
-	dest := fmt.Sprintf("%s/foo.pdf", dirPath)
-	err = c.Store(req, dest)
-	assert.Nil(t, err)
-	assert.FileExists(t, dest)
-	err = os.RemoveAll(dirPath)
-	assert.Nil(t, err)
-}
-
-func TestConcurrentURL(t *testing.T) {
-	for i := 0; i < 10; i++ {
-		go func() {
-			TestURL(t)
-		}()
-	}
-}
diff --git a/test/testfunc.go b/test/testfunc.go
index 3c176a57..20ab67cf 100644
--- a/test/testfunc.go
+++ b/test/testfunc.go
@@ -138,36 +138,6 @@ func copyDir(t *testing.T, kind string) string {
 	return tmpDirPath
 }
 
-// HTMLTestFilePath returns the absolute file path
-// of a file in "html" folder in test/testdata.
-func HTMLTestFilePath(t *testing.T, filename string) string {
-	return abs(t, "html", filename)
-}
-
-// URLTestFilePath returns the absolute file path
-// of a file in "url" folder in test/testdata.
-func URLTestFilePath(t *testing.T, filename string) string {
-	return abs(t, "url", filename)
-}
-
-// MarkdownTestFilePath returns the absolute file path
-// of a file in "markdown" folder in test/testdata.
-func MarkdownTestFilePath(t *testing.T, filename string) string {
-	return abs(t, "markdown", filename)
-}
-
-// OfficeTestFilePath returns the absolute file path
-// of a file in "office" folder in test/testdata.
-func OfficeTestFilePath(t *testing.T, filename string) string {
-	return abs(t, "office", filename)
-}
-
-// PDFTestFilePath returns the absolute file path
-// of a file in "pdf" folder in test/testdata.
-func PDFTestFilePath(t *testing.T, filename string) string {
-	return abs(t, "pdf", filename)
-}
-
 func abs(t *testing.T, kind, filename string) string {
 	_, gofilename, _, ok := runtime.Caller(0)
 	require.Equal(t, ok, true, "got no caller information")