Compare commits

..

5 Commits
3.1.0 ... 3.1.1

Author SHA1 Message Date
Julien Neuhart
4c1699df6c webhook: resulting file was deleted because of defer outside of goroutine 2018-12-13 18:15:28 +01:00
Julien Neuhart
404535c512 fixing/simplifying godoc 2018-12-13 17:06:29 +01:00
Julien Neuhart
2cedcecc38 adding concurrent testing 2018-12-13 14:46:59 +01:00
Julien Neuhart
ba7b02d8d4 fixing various typos in documentation 2018-12-12 17:44:27 +01:00
Julien Neuhart
6aa3c16646 fixing golang client README 2018-12-12 16:44:32 +01:00
17 changed files with 89 additions and 100 deletions

View File

@@ -273,7 +273,7 @@ func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req, _ := gotenberg.NewHTMLRequest("index.html")
req.SetPaperSize(gotenberg.A4)
req.SetMargins(gotenberg.NormalMargins)
req.SetMargins(gotenberg.NoMargins)
req.SetLandscape(true)
dest := "result.pdf"
c.Store(req, dest)

View File

@@ -119,7 +119,6 @@ $files = [
];
$request = new OfficeRequest($files);
$request->setPaperSize(Request::A4);
$request->setMargins(Request::NO_MARGINS);
$request->setLandscape(true);
$dirPath = "/foo";
$filename = $client->store($request, $dirPath);

View File

@@ -28,14 +28,10 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.HTMLRequest{
IndexFilePath: "index.html",
Options: &gotenberg.HTMLOptions{
WebHookURL: "http://myapp.com/webhook/",
},
}
req, _ := gotenberg.NewHTMLRequest("index.html")
req.SetWebhookURL("http://myapp.com/webhook/")
dest := "result.pdf"
resp, err := c.Post(req)
resp, _ := c.Post(req)
}
```

View File

@@ -21,4 +21,5 @@ go test github.com/thecodingmachine/gotenberg/internal/pkg/pm2 -run TestUnoconvS
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
go test -race -cover -covermode=atomic github.com/thecodingmachine/gotenberg/pkg
sleep 5 # allows Gotenberg to remove generated files (concurrent requests).

View File

@@ -437,7 +437,7 @@ Also, you have to set both <code>paperWidth</code> and <code>paperHeight</code>.
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewHTMLRequest</span><span class="p">(</span><span class="s">&#34;index.html&#34;</span><span class="p">)</span>
<span class="nx">req</span><span class="p">.</span><span class="nx">SetPaperSize</span><span class="p">(</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">A4</span><span class="p">)</span>
<span class="nx">req</span><span class="p">.</span><span class="nx">SetMargins</span><span class="p">(</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NormalMargins</span><span class="p">)</span>
<span class="nx">req</span><span class="p">.</span><span class="nx">SetMargins</span><span class="p">(</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NoMargins</span><span class="p">)</span>
<span class="nx">req</span><span class="p">.</span><span class="nx">SetLandscape</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span>
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
@@ -679,7 +679,6 @@ Also, you have to set both <code>paperWidth</code> and <code>paperHeight</code>.
</span><span class="x">];
</span><span class="x">$request = new OfficeRequest($files);
</span><span class="x">$request-&gt;setPaperSize(Request::A4);
</span><span class="x">$request-&gt;setMargins(Request::NO_MARGINS);
</span><span class="x">$request-&gt;setLandscape(true);
</span><span class="x">$dirPath = &#34;/foo&#34;;
</span><span class="x">$filename = $client-&gt;store($request, $dirPath);
@@ -795,14 +794,10 @@ to given URL.</p>
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</span><span class="p">{</span>
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">&#34;index.html&#34;</span><span class="p">,</span>
<span class="nx">Options</span><span class="p">:</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLOptions</span><span class="p">{</span>
<span class="nx">WebHookURL</span><span class="p">:</span> <span class="s">&#34;http://myapp.com/webhook/&#34;</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewHTMLRequest</span><span class="p">(</span><span class="s">&#34;index.html&#34;</span><span class="p">)</span>
<span class="nx">req</span><span class="p">.</span><span class="nx">SetWebhookURL</span><span class="p">(</span><span class="s">&#34;http://myapp.com/webhook/&#34;</span><span class="p">)</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span>
<span class="nx">resp</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">c</span><span class="p">.</span><span class="nx">Post</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
<span class="nx">resp</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">c</span><span class="p">.</span><span class="nx">Post</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
<span class="p">}</span>
</pre>

View File

@@ -87,14 +87,15 @@ func newContext(r *resource) (context.Context, context.CancelFunc) {
func print(c echo.Context, p printer.Printer, r *resource) error {
baseFilename, err := rand.Get()
if err != nil {
return fmt.Errorf("getting result file name: %v", err)
return hijackErr(fmt.Errorf("getting result file name: %v", err), r)
}
filename := fmt.Sprintf("%s.pdf", baseFilename)
fpath := fmt.Sprintf("%s/%s", r.dirPath, filename)
if r.webhookURL() == "" {
defer r.removeAll()
// if no webhook URL given, run conversion
// and directly return the resulting PDF file
// or and error.
// or an error.
if err := p.Print(fpath); err != nil {
return err
}
@@ -104,6 +105,7 @@ func print(c echo.Context, p printer.Printer, r *resource) error {
// run the following lines in a goroutine so that
// it doesn't block.
go func() {
defer r.removeAll()
if err := p.Print(fpath); err != nil {
c.Logger().Errorf("%v", err)
return
@@ -123,3 +125,10 @@ func print(c echo.Context, p printer.Printer, r *resource) error {
}()
return nil
}
func hijackErr(err error, r *resource) error {
if r != nil {
defer r.removeAll()
}
return err
}

View File

@@ -8,9 +8,8 @@ import (
func convertHTML(c echo.Context) error {
r, err := newResource(c)
if err != nil {
return err
return hijackErr(err, r)
}
defer r.removeAll()
ctx, cancel := newContext(r)
if cancel != nil {
defer cancel()
@@ -18,26 +17,26 @@ func convertHTML(c echo.Context) error {
p := &printer.HTML{Context: ctx}
indexPath, err := r.filePath("index.html")
if err != nil {
return err
return hijackErr(err, r)
}
p.WithLocalURL(indexPath)
headerPath, _ := r.filePath("header.html")
if err := p.WithHeaderFile(headerPath); err != nil {
return err
return hijackErr(err, r)
}
footerPath, _ := r.filePath("footer.html")
if err := p.WithFooterFile(footerPath); err != nil {
return err
return hijackErr(err, r)
}
paperSize, err := r.paperSize()
if err != nil {
return err
return hijackErr(err, r)
}
p.PaperWidth = paperSize[0]
p.PaperHeight = paperSize[1]
paperMargins, err := r.paperMargins()
if err != nil {
return err
return hijackErr(err, r)
}
p.MarginTop = paperMargins[0]
p.MarginBottom = paperMargins[1]
@@ -45,7 +44,7 @@ func convertHTML(c echo.Context) error {
p.MarginRight = paperMargins[3]
landscape, err := r.landscape()
if err != nil {
return err
return hijackErr(err, r)
}
p.Landscape = landscape
return print(c, p, r)

View File

@@ -8,35 +8,34 @@ import (
func convertMarkdown(c echo.Context) error {
r, err := newResource(c)
if err != nil {
return err
return hijackErr(err, r)
}
defer r.removeAll()
ctx, cancel := newContext(r)
if cancel != nil {
defer cancel()
}
indexPath, err := r.filePath("index.html")
if err != nil {
return err
return hijackErr(err, r)
}
p := &printer.Markdown{Context: ctx, TemplatePath: indexPath}
headerPath, _ := r.filePath("header.html")
if err := p.WithHeaderFile(headerPath); err != nil {
return err
return hijackErr(err, r)
}
footerPath, _ := r.filePath("footer.html")
if err := p.WithFooterFile(footerPath); err != nil {
return err
return hijackErr(err, r)
}
paperSize, err := r.paperSize()
if err != nil {
return err
return hijackErr(err, r)
}
p.PaperWidth = paperSize[0]
p.PaperHeight = paperSize[1]
paperMargins, err := r.paperMargins()
if err != nil {
return err
return hijackErr(err, r)
}
p.MarginTop = paperMargins[0]
p.MarginBottom = paperMargins[1]
@@ -44,7 +43,7 @@ func convertMarkdown(c echo.Context) error {
p.MarginRight = paperMargins[3]
landscape, err := r.landscape()
if err != nil {
return err
return hijackErr(err, r)
}
p.Landscape = landscape
return print(c, p, r)

View File

@@ -1,6 +1,7 @@
package api
import (
"errors"
"fmt"
"net/http"
"os"
@@ -13,23 +14,26 @@ import (
func merge(c echo.Context) error {
r, err := newResource(c)
if err != nil {
return err
return hijackErr(err, r)
}
defer r.removeAll()
fpaths, err := r.filePaths([]string{".pdf"})
if err != nil {
return err
return hijackErr(err, r)
}
if len(fpaths) == 0 {
return hijackErr(errors.New("no suitable PDF files to merge"), r)
}
baseFilename, err := rand.Get()
if err != nil {
return fmt.Errorf("getting result file name: %v", err)
return hijackErr(fmt.Errorf("getting result file name: %v", err), r)
}
filename := fmt.Sprintf("%s.pdf", baseFilename)
fpath := fmt.Sprintf("%s/%s", r.dirPath, filename)
if r.webhookURL() == "" {
defer r.removeAll()
// if no webhook URL given, run merge
// and directly return the resulting PDF file
// or and error.
// or an error.
if err := printer.Merge(fpaths, fpath); err != nil {
return err
}
@@ -39,6 +43,7 @@ func merge(c echo.Context) error {
// run the following lines in a goroutine so that
// it doesn't block.
go func() {
defer r.removeAll()
if err := printer.Merge(fpaths, fpath); err != nil {
c.Logger().Errorf("%v", err)
return

View File

@@ -24,30 +24,29 @@ var officeExts = []string{
func convertOffice(c echo.Context) error {
r, err := newResource(c)
if err != nil {
return err
return hijackErr(err, r)
}
defer r.removeAll()
ctx, cancel := newContext(r)
if cancel != nil {
defer cancel()
}
fpaths, err := r.filePaths(officeExts)
if err != nil {
return err
return hijackErr(err, r)
}
if len(fpaths) == 0 {
return errors.New("no suitable office documents to convert")
return hijackErr(errors.New("no suitable office documents to convert"), r)
}
p := &printer.Office{Context: ctx, FilePaths: fpaths}
paperSize, err := r.paperSize()
if err != nil {
return err
return hijackErr(err, r)
}
p.PaperWidth = paperSize[0]
p.PaperHeight = paperSize[1]
landscape, err := r.landscape()
if err != nil {
return err
return hijackErr(err, r)
}
p.Landscape = landscape
return print(c, p, r)

View File

@@ -49,17 +49,17 @@ func newResource(c echo.Context) (*resource, error) {
r := &resource{values: v, dirPath: dirPath}
form, err := c.MultipartForm()
if err != nil {
return nil, fmt.Errorf("getting multipart form: %v", err)
return r, 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)
return r, 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, err
}
}
}

View File

@@ -1,52 +1,7 @@
/*
Package printer contains structs which convert
a specific file type to PDF:
a specific file type to PDF.
// converting HTML to PDF.
p := &printer.HTML{
Context: context.Background(),
PaperWidth: 8.27,
PaperHeight: 11.7,
Landscape: false,
}
p.WithLocalURL("index.html")
if err := p.Print("result.pdf"); err != nil {
return err
}
// converting Markdown to PDF:
// it assumes here that our template "index.html"
// will call toHTML method to convert
// markdown files to HTML.
p := &printer.Markdown{
Context: context.Background(),
TemplatePath: "index.html",
PaperWidth: 8.27,
PaperHeight: 11.7,
Landscape: false,
}
if err := p.Print("result.pdf"); err != nil {
return err
}
// converting Office documents to PDF:
// it converts each files independently and
// then merge them.
//
// Also, as unoconv cannot perform
// concurrent conversions, a lock is applied.
p := &printer.Office{
Context: ctx,
FilePaths: []string{"document.docx", "presentation.pptx"}
}
if err := p.Print("result.pdf"); err != nil {
return err
}
It is also able to merge a list of PDF files:
if err := printer.Merge([]string{"foo.pdf", "bar.pdf"}, "result.pdf"); err != nil {
return err
}
It is also able to merge a list of PDF files.
*/
package printer

View File

@@ -24,8 +24,8 @@ func main() {
"img.gif",
"style.css",
})
req.SetPaperSize(A4)
req.SetMargins(NormalMargins)
req.SetPaperSize(gotenberg.A4)
req.SetMargins(gotenberg.NormalMargins)
req.SetLandscape(false)
dest := "foo.pdf"
c.Store(req, dest)

View File

@@ -37,3 +37,11 @@ func TestHTML(t *testing.T) {
err = os.RemoveAll(dirPath)
assert.Nil(t, err)
}
func TestConcurrentHTML(t *testing.T) {
for i := 0; i < 10; i++ {
go func() {
TestHTML(t)
}()
}
}

View File

@@ -44,3 +44,11 @@ func TestMarkdown(t *testing.T) {
err = os.RemoveAll(dirPath)
assert.Nil(t, err)
}
func TestConcurrentMarkdown(t *testing.T) {
for i := 0; i < 10; i++ {
go func() {
TestMarkdown(t)
}()
}
}

View File

@@ -27,3 +27,11 @@ func TestMerge(t *testing.T) {
err = os.RemoveAll(dirPath)
assert.Nil(t, err)
}
func TestConcurrentMerge(t *testing.T) {
for i := 0; i < 10; i++ {
go func() {
TestMerge(t)
}()
}
}

View File

@@ -28,3 +28,11 @@ func TestOffice(t *testing.T) {
err = os.RemoveAll(dirPath)
assert.Nil(t, err)
}
func TestConcurrentOffice(t *testing.T) {
for i := 0; i < 10; i++ {
go func() {
TestOffice(t)
}()
}
}