diff --git a/README.md b/README.md index 86c6a41..e4c2acb 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,20 @@ Aimed to be a simple, fast and easy-to-use webarchive for personal or home-net u The service can be configured via environment variables. There is a list of available variables: -* **DB_PATH** — path for the database files (default `./db`) -* **LOGGING_DEBUG** — enable debug logs (default `false`) +* **DB** + * **DB_PATH** — path for the database files (default `./db`) +* **LOGGING** + * **LOGGING_DEBUG** — enable debug logs (default `false`) +* **API** + * **API_ADDRESS** — address the API server will listen (default `0.0.0.0:5001`) +* **PDF** + * **PDF_LANDSCAPE** — use landscape page orientation instead of portrait (default `false`) + * **PDF_GRAYSCALE** — use grayscale filter for the output pdf (default `false`) + * **PDF_MEDIA_PRINT** — use media type `print` for the request (default `true`) + * **PDF_ZOOM** — zoom page (default `1.0` i.e. no actual zoom) + * **PDF_VIEWPORT** — use specified viewport value (default `1920x1080`) + * **PDF_DPI** — use specified DPI value for the output pdf (default `300`) + * **PDF_FILENAME** — use specified name for output pdf file (default `page.pdf`) *Note*: Prefix **WEBARCHIVE_** can be used with the environment variable names @@ -80,4 +92,3 @@ curl -X GET --location "http://localhost:5001/pages" | jq . - [ ] Optional authentication - [ ] Multi-user access - [ ] Support PostgreSQL -- [ ] Extend configuration diff --git a/adapters/processors/pdf.go b/adapters/processors/pdf.go index a852c4e..235d250 100644 --- a/adapters/processors/pdf.go +++ b/adapters/processors/pdf.go @@ -7,37 +7,46 @@ import ( "github.com/SebastiaanKlippert/go-wkhtmltopdf" + "github.com/derfenix/webarchive/config" "github.com/derfenix/webarchive/entity" ) -func NewPDF() *PDF { - return &PDF{} +func NewPDF(cfg config.PDF) *PDF { + return &PDF{cfg: cfg} } -type PDF struct{} +type PDF struct { + cfg config.PDF +} -func (P *PDF) Process(_ context.Context, url string) ([]entity.File, error) { +func (p *PDF) Process(_ context.Context, url string) ([]entity.File, error) { gen, err := wkhtmltopdf.NewPDFGenerator() if err != nil { return nil, fmt.Errorf("new pdf generator: %w", err) } - gen.Dpi.Set(300) + gen.Dpi.Set(p.cfg.DPI) gen.PageSize.Set(wkhtmltopdf.PageSizeA4) - gen.Orientation.Set(wkhtmltopdf.OrientationPortrait) - gen.Grayscale.Set(false) + + if p.cfg.Landscape { + gen.Orientation.Set(wkhtmltopdf.OrientationLandscape) + } else { + gen.Orientation.Set(wkhtmltopdf.OrientationPortrait) + } + + gen.Grayscale.Set(p.cfg.Grayscale) gen.Title.Set(url) page := wkhtmltopdf.NewPage(url) - page.PrintMediaType.Set(true) + page.PrintMediaType.Set(p.cfg.MediaPrint) page.JavascriptDelay.Set(200) page.LoadMediaErrorHandling.Set("ignore") page.FooterRight.Set("[page]") page.HeaderLeft.Set(url) page.HeaderRight.Set(time.Now().Format(time.DateOnly)) page.FooterFontSize.Set(10) - page.Zoom.Set(1) - page.ViewportSize.Set("1920x1080") + page.Zoom.Set(p.cfg.Zoom) + page.ViewportSize.Set(p.cfg.Viewport) gen.AddPage(page) @@ -46,7 +55,7 @@ func (P *PDF) Process(_ context.Context, url string) ([]entity.File, error) { return nil, fmt.Errorf("create pdf: %w", err) } - file := entity.NewFile("page.pdf", gen.Bytes()) + file := entity.NewFile(p.cfg.Filename, gen.Bytes()) return []entity.File{file}, nil } diff --git a/adapters/processors/processors.go b/adapters/processors/processors.go index 88f0a43..6909084 100644 --- a/adapters/processors/processors.go +++ b/adapters/processors/processors.go @@ -8,6 +8,7 @@ import ( "net/http/cookiejar" "time" + "github.com/derfenix/webarchive/config" "github.com/derfenix/webarchive/entity" ) @@ -15,7 +16,7 @@ type processor interface { Process(ctx context.Context, url string) ([]entity.File, error) } -func NewProcessors() (*Processors, error) { +func NewProcessors(cfg config.Config) (*Processors, error) { jar, err := cookiejar.New(&cookiejar.Options{ PublicSuffixList: nil, }) @@ -53,7 +54,7 @@ func NewProcessors() (*Processors, error) { procs := Processors{ processors: map[entity.Format]processor{ entity.FormatHeaders: NewHeaders(httpClient), - entity.FormatPDF: NewPDF(), + entity.FormatPDF: NewPDF(cfg.PDF), }, } diff --git a/application/application.go b/application/application.go index 0e0ad92..9a344b8 100644 --- a/application/application.go +++ b/application/application.go @@ -18,11 +18,12 @@ import ( "github.com/derfenix/webarchive/adapters/processors" badgerRepo "github.com/derfenix/webarchive/adapters/repository/badger" "github.com/derfenix/webarchive/api/openapi" + "github.com/derfenix/webarchive/config" "github.com/derfenix/webarchive/entity" "github.com/derfenix/webarchive/ports/rest" ) -func NewApplication(cfg Config) (Application, error) { +func NewApplication(cfg config.Config) (Application, error) { log, err := newLogger(cfg.Logging) if err != nil { return Application{}, fmt.Errorf("new logger: %w", err) @@ -38,7 +39,7 @@ func NewApplication(cfg Config) (Application, error) { return Application{}, fmt.Errorf("new page repo: %w", err) } - processor, err := processors.NewProcessors() + processor, err := processors.NewProcessors(cfg) if err != nil { return Application{}, fmt.Errorf("new processors: %w", err) } @@ -73,7 +74,7 @@ func NewApplication(cfg Config) (Application, error) { } httpServer := http.Server{ - Addr: "0.0.0.0:5001", + Addr: cfg.API.Address, Handler: server, ReadTimeout: time.Second * 15, ReadHeaderTimeout: time.Second * 5, @@ -94,7 +95,7 @@ func NewApplication(cfg Config) (Application, error) { } type Application struct { - cfg Config + cfg config.Config log *zap.Logger db *badger.DB processor entity.Processor @@ -165,7 +166,7 @@ func (a *Application) Stop() error { return errs } -func newLogger(cfg Logging) (*zap.Logger, error) { +func newLogger(cfg config.Logging) (*zap.Logger, error) { logCfg := zap.NewProductionConfig() logCfg.EncoderConfig.EncodeTime = zapcore.RFC3339TimeEncoder logCfg.EncoderConfig.EncodeDuration = zapcore.NanosDurationEncoder diff --git a/cmd/service/main.go b/cmd/service/main.go index acecf8b..83f6b20 100644 --- a/cmd/service/main.go +++ b/cmd/service/main.go @@ -10,13 +10,14 @@ import ( "go.uber.org/zap" "github.com/derfenix/webarchive/application" + "github.com/derfenix/webarchive/config" ) func main() { ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) defer cancel() - cfg, err := application.NewConfig(ctx) + cfg, err := config.NewConfig(ctx) if err != nil { fmt.Printf("failed to init config: %s", err.Error()) os.Exit(2) diff --git a/application/config.go b/config/config.go similarity index 55% rename from application/config.go rename to config/config.go index 90bdf13..8e2f7ed 100644 --- a/application/config.go +++ b/config/config.go @@ -1,4 +1,4 @@ -package application +package config import ( "context" @@ -27,6 +27,22 @@ func NewConfig(ctx context.Context) (Config, error) { type Config struct { DB DB `env:",prefix=DB_"` Logging Logging `env:",prefix=LOGGING_"` + API API `env:",prefix=API_"` + PDF PDF `env:",prefix=PDF_"` +} + +type PDF struct { + Landscape bool `env:"LANDSCAPE,default=false"` + Grayscale bool `env:"GRAYSCALE,default=false"` + MediaPrint bool `env:"MEDIA_PRINT,default=true"` + Zoom float64 `env:"ZOOM,default=1"` + Viewport string `env:"VIEWPORT,default=1920x1080"` + DPI uint `env:"DPI,default=300"` + Filename string `env:"FILENAME,default=page.pdf"` +} + +type API struct { + Address string `env:"ADDRESS,default=0.0.0.0:5001"` } type DB struct { diff --git a/application/config_test.go b/config/config_test.go similarity index 97% rename from application/config_test.go rename to config/config_test.go index 6aa4af8..f4c73f3 100644 --- a/application/config_test.go +++ b/config/config_test.go @@ -1,4 +1,4 @@ -package application +package config import ( "context"