mirror of
https://github.com/derfenix/webarchive.git
synced 2026-03-11 12:41:54 +03:00
Extend configuration
This commit is contained in:
17
README.md
17
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
|
The service can be configured via environment variables. There is a list of available
|
||||||
variables:
|
variables:
|
||||||
|
|
||||||
* **DB_PATH** — path for the database files (default `./db`)
|
* **DB**
|
||||||
* **LOGGING_DEBUG** — enable debug logs (default `false`)
|
* **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
|
*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
|
- [ ] Optional authentication
|
||||||
- [ ] Multi-user access
|
- [ ] Multi-user access
|
||||||
- [ ] Support PostgreSQL
|
- [ ] Support PostgreSQL
|
||||||
- [ ] Extend configuration
|
|
||||||
|
|||||||
@@ -7,37 +7,46 @@ import (
|
|||||||
|
|
||||||
"github.com/SebastiaanKlippert/go-wkhtmltopdf"
|
"github.com/SebastiaanKlippert/go-wkhtmltopdf"
|
||||||
|
|
||||||
|
"github.com/derfenix/webarchive/config"
|
||||||
"github.com/derfenix/webarchive/entity"
|
"github.com/derfenix/webarchive/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewPDF() *PDF {
|
func NewPDF(cfg config.PDF) *PDF {
|
||||||
return &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()
|
gen, err := wkhtmltopdf.NewPDFGenerator()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new pdf generator: %w", err)
|
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.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)
|
gen.Title.Set(url)
|
||||||
|
|
||||||
page := wkhtmltopdf.NewPage(url)
|
page := wkhtmltopdf.NewPage(url)
|
||||||
page.PrintMediaType.Set(true)
|
page.PrintMediaType.Set(p.cfg.MediaPrint)
|
||||||
page.JavascriptDelay.Set(200)
|
page.JavascriptDelay.Set(200)
|
||||||
page.LoadMediaErrorHandling.Set("ignore")
|
page.LoadMediaErrorHandling.Set("ignore")
|
||||||
page.FooterRight.Set("[page]")
|
page.FooterRight.Set("[page]")
|
||||||
page.HeaderLeft.Set(url)
|
page.HeaderLeft.Set(url)
|
||||||
page.HeaderRight.Set(time.Now().Format(time.DateOnly))
|
page.HeaderRight.Set(time.Now().Format(time.DateOnly))
|
||||||
page.FooterFontSize.Set(10)
|
page.FooterFontSize.Set(10)
|
||||||
page.Zoom.Set(1)
|
page.Zoom.Set(p.cfg.Zoom)
|
||||||
page.ViewportSize.Set("1920x1080")
|
page.ViewportSize.Set(p.cfg.Viewport)
|
||||||
|
|
||||||
gen.AddPage(page)
|
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)
|
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
|
return []entity.File{file}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/derfenix/webarchive/config"
|
||||||
"github.com/derfenix/webarchive/entity"
|
"github.com/derfenix/webarchive/entity"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ type processor interface {
|
|||||||
Process(ctx context.Context, url string) ([]entity.File, error)
|
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{
|
jar, err := cookiejar.New(&cookiejar.Options{
|
||||||
PublicSuffixList: nil,
|
PublicSuffixList: nil,
|
||||||
})
|
})
|
||||||
@@ -53,7 +54,7 @@ func NewProcessors() (*Processors, error) {
|
|||||||
procs := Processors{
|
procs := Processors{
|
||||||
processors: map[entity.Format]processor{
|
processors: map[entity.Format]processor{
|
||||||
entity.FormatHeaders: NewHeaders(httpClient),
|
entity.FormatHeaders: NewHeaders(httpClient),
|
||||||
entity.FormatPDF: NewPDF(),
|
entity.FormatPDF: NewPDF(cfg.PDF),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,12 @@ import (
|
|||||||
"github.com/derfenix/webarchive/adapters/processors"
|
"github.com/derfenix/webarchive/adapters/processors"
|
||||||
badgerRepo "github.com/derfenix/webarchive/adapters/repository/badger"
|
badgerRepo "github.com/derfenix/webarchive/adapters/repository/badger"
|
||||||
"github.com/derfenix/webarchive/api/openapi"
|
"github.com/derfenix/webarchive/api/openapi"
|
||||||
|
"github.com/derfenix/webarchive/config"
|
||||||
"github.com/derfenix/webarchive/entity"
|
"github.com/derfenix/webarchive/entity"
|
||||||
"github.com/derfenix/webarchive/ports/rest"
|
"github.com/derfenix/webarchive/ports/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewApplication(cfg Config) (Application, error) {
|
func NewApplication(cfg config.Config) (Application, error) {
|
||||||
log, err := newLogger(cfg.Logging)
|
log, err := newLogger(cfg.Logging)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Application{}, fmt.Errorf("new logger: %w", err)
|
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)
|
return Application{}, fmt.Errorf("new page repo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
processor, err := processors.NewProcessors()
|
processor, err := processors.NewProcessors(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Application{}, fmt.Errorf("new processors: %w", err)
|
return Application{}, fmt.Errorf("new processors: %w", err)
|
||||||
}
|
}
|
||||||
@@ -73,7 +74,7 @@ func NewApplication(cfg Config) (Application, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
httpServer := http.Server{
|
httpServer := http.Server{
|
||||||
Addr: "0.0.0.0:5001",
|
Addr: cfg.API.Address,
|
||||||
Handler: server,
|
Handler: server,
|
||||||
ReadTimeout: time.Second * 15,
|
ReadTimeout: time.Second * 15,
|
||||||
ReadHeaderTimeout: time.Second * 5,
|
ReadHeaderTimeout: time.Second * 5,
|
||||||
@@ -94,7 +95,7 @@ func NewApplication(cfg Config) (Application, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Application struct {
|
type Application struct {
|
||||||
cfg Config
|
cfg config.Config
|
||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
db *badger.DB
|
db *badger.DB
|
||||||
processor entity.Processor
|
processor entity.Processor
|
||||||
@@ -165,7 +166,7 @@ func (a *Application) Stop() error {
|
|||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLogger(cfg Logging) (*zap.Logger, error) {
|
func newLogger(cfg config.Logging) (*zap.Logger, error) {
|
||||||
logCfg := zap.NewProductionConfig()
|
logCfg := zap.NewProductionConfig()
|
||||||
logCfg.EncoderConfig.EncodeTime = zapcore.RFC3339TimeEncoder
|
logCfg.EncoderConfig.EncodeTime = zapcore.RFC3339TimeEncoder
|
||||||
logCfg.EncoderConfig.EncodeDuration = zapcore.NanosDurationEncoder
|
logCfg.EncoderConfig.EncodeDuration = zapcore.NanosDurationEncoder
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/derfenix/webarchive/application"
|
"github.com/derfenix/webarchive/application"
|
||||||
|
"github.com/derfenix/webarchive/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
cfg, err := application.NewConfig(ctx)
|
cfg, err := config.NewConfig(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to init config: %s", err.Error())
|
fmt.Printf("failed to init config: %s", err.Error())
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package application
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -27,6 +27,22 @@ func NewConfig(ctx context.Context) (Config, error) {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
DB DB `env:",prefix=DB_"`
|
DB DB `env:",prefix=DB_"`
|
||||||
Logging Logging `env:",prefix=LOGGING_"`
|
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 {
|
type DB struct {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package application
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
Reference in New Issue
Block a user