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

Commit

Permalink
extracted convert to PDF in a plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
dstpierre committed May 17, 2024
1 parent 6ec5bf1 commit b3ed465
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 44 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:

- name: Build
run: make build

- name: Set PLUGINS_PATH env var
run: export PLUGINS_PATH=$(pwd)/plugins

- name: Test (PostgreSQL data store)
run: make alltest
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ build:
-X github.com/staticbackendhq/core/config.CommitHash=$(shell git log --pretty=format:'%h' -n 1) \
-X github.com/staticbackendhq/core/config.Version=$(shell git describe --tags)" \
-o staticbackend
@cd plugins/topdf && CGO_ENABLE=0 go build -buildmode=plugin -o ../topdf.so

start: build
@./cmd/staticbackend
Expand Down Expand Up @@ -63,8 +64,11 @@ pkg: build
@cd cmd && CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o ../dist/binary-for-linux-64-bit
@cd cmd && CGO_ENABLED=0 GOARCH=386 GOOS=linux go build -o ../dist/binary-for-linux-32-bit
@echo "building mac binaries"
@cd cmd && CGO_ENABLED=0 GOARCH=amd64 GOOS=darwin go build -o ../dist/binary-for-mac-64-bit
@cd cmd && CGO_ENABLED=0 GOARCH=amd64 GOOS=darwin go build -o ../dist/binary-for-intel-mac-64-bit
@cd cmd && CGO_ENABLED=0 GOARCH=arm64 GOOS=darwin go build -o ../dist/binary-for-arm-mac-64-bit
@echo "building windows binaries"
@cd cmd && CGO_ENABLED=0 GOARCH=amd64 GOOS=windows go build -o ../dist/binary-for-windows-64-bit.exe
@echo copying plugins
@cp plugins/*.so dist/
@echo "compressing binaries"
@gzip dist/*
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ type AppConfig struct {
FullTextIndexFile string
// ActivateFlag when set, the /account/init can bypass Stripe if matching val
ActivateFlag string
// PluginsPath is the full qualified path where plugins are stored
PluginsPath string
}

func LoadConfig() AppConfig {
Expand Down Expand Up @@ -127,5 +129,6 @@ func LoadConfig() AppConfig {
LogFilename: os.Getenv("LOG_FILENAME"),
FullTextIndexFile: os.Getenv("FTS_INDEX_FILE"),
ActivateFlag: os.Getenv("ACTIVATE_FLAG"),
PluginsPath: os.Getenv("PLUGINS_PATH"),
}
}
77 changes: 36 additions & 41 deletions extras.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ package staticbackend

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"path"
"path/filepath"
"plugin"
"strconv"
"time"

"github.com/chromedp/cdproto/page"
"github.com/chromedp/chromedp"
"github.com/staticbackendhq/core/backend"
"github.com/staticbackendhq/core/config"
"github.com/staticbackendhq/core/extra"
"github.com/staticbackendhq/core/internal"
"github.com/staticbackendhq/core/logger"
Expand Down Expand Up @@ -129,7 +131,8 @@ func (ex *extras) sudoSendSMS(w http.ResponseWriter, r *http.Request) {
respond(w, http.StatusOK, true)
}

type ConvertParam struct {
// ConvertParams is also replicated in the plugin implementation
type ConvertParams struct {
ToPDF bool `json:"toPDF"`
URL string `json:"url"`
FullPage bool `json:"fullpage"`
Expand All @@ -142,23 +145,22 @@ func (ex *extras) htmlToX(w http.ResponseWriter, r *http.Request) {
return
}

var data ConvertParam
if err := parseBody(r.Body, &data); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
r.Body.Close()

/*opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("disable-gpu", true),
)*/

ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()

var buf []byte
var data ConvertParams
if err := json.Unmarshal(body, &data); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

if err := chromedp.Run(ctx, ex.toBytes(data, &buf)); err != nil {
http.Error(w, fmt.Sprintf("htmltox chromedp run %s", err.Error()), http.StatusInternalServerError)
buf, err := convertToPDF(body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

Expand Down Expand Up @@ -208,29 +210,22 @@ func (ex *extras) htmlToX(w http.ResponseWriter, r *http.Request) {
respond(w, http.StatusOK, data)
}

func (ex *extras) toBytes(data ConvertParam, res *[]byte) chromedp.Tasks {
return chromedp.Tasks{
chromedp.EmulateViewport(1280, 768),
chromedp.Navigate(data.URL),
chromedp.WaitReady("body"),
chromedp.ActionFunc(func(ctx context.Context) error {
var buf []byte
var err error
if data.ToPDF {
buf, _, err = page.PrintToPDF().Do(ctx)
} else {
params := page.CaptureScreenshot()
// TODO: This should capture full screen ?!?
params.CaptureBeyondViewport = data.FullPage

buf, err = params.Do(ctx)
}
if err != nil {
return err
}

*res = buf
return nil
}),
func convertToPDF(body []byte) ([]byte, error) {
ppath := path.Join(config.Current.PluginsPath, "topdf.so")
p, err := plugin.Open(ppath)
if err != nil {
return nil, err
}

fn, err := p.Lookup("Do")
if err != nil {
return nil, err
}

f, ok := fn.(func(data []byte) ([]byte, error))
if !ok {
return nil, fmt.Errorf("unable to cast ToPDF to func([]byte) ([]byte, error)")
}

return f(body)
}
4 changes: 2 additions & 2 deletions extras_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func TestHtmlToPDF(t *testing.T) {
// TODO: this is intermitant and when it failes it's with that
// error line:128: context deadline exceeded

data := ConvertParam{
data := ConvertParams{
ToPDF: true,
URL: "https://staticbackend.com",
}
Expand All @@ -142,7 +142,7 @@ func TestHtmlToPNG(t *testing.T) {
//
// we need to determine why it's doing this and remove the Skip

data := ConvertParam{
data := ConvertParams{
ToPDF: false,
URL: "https://staticbackend.com",
FullPage: true,
Expand Down
59 changes: 59 additions & 0 deletions plugins/topdf/topdf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package main

import (
"context"
"encoding/json"

"github.com/chromedp/cdproto/page"
"github.com/chromedp/chromedp"
)

type ConvertParams struct {
ToPDF bool `json:"toPDF"`
URL string `json:"url"`
FullPage bool `json:"fullpage"`
}

func Do(body []byte) (buf []byte, err error) {
var data ConvertParams
if err = json.Unmarshal(body, &data); err != nil {
return
}

/*opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("disable-gpu", true),
)*/

ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()

err = chromedp.Run(ctx, toBytes(data, &buf))
return buf, err
}

func toBytes(data ConvertParams, res *[]byte) chromedp.Tasks {
return chromedp.Tasks{
chromedp.EmulateViewport(1280, 768),
chromedp.Navigate(data.URL),
chromedp.WaitReady("body"),
chromedp.ActionFunc(func(ctx context.Context) error {
var buf []byte
var err error
if data.ToPDF {
buf, _, err = page.PrintToPDF().Do(ctx)
} else {
params := page.CaptureScreenshot()
// TODO: This should capture full screen ?!?
params.CaptureBeyondViewport = data.FullPage

buf, err = params.Do(ctx)
}
if err != nil {
return err
}

*res = buf
return nil
}),
}
}

0 comments on commit b3ed465

Please sign in to comment.