From b1d94a3845f2666ddb36482d125f9890b8271847 Mon Sep 17 00:00:00 2001 From: Julien Neuhart Date: Wed, 12 Jun 2024 20:41:02 +0200 Subject: [PATCH] feat(chromium): add user agent override --- pkg/modules/chromium/browser.go | 2 ++ pkg/modules/chromium/browser_test.go | 38 ++++++++++++++++++++++++++++ pkg/modules/chromium/chromium.go | 9 +++++-- pkg/modules/chromium/routes.go | 3 +++ pkg/modules/chromium/tasks.go | 17 +++++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) diff --git a/pkg/modules/chromium/browser.go b/pkg/modules/chromium/browser.go index d7a30326..fd84915c 100644 --- a/pkg/modules/chromium/browser.go +++ b/pkg/modules/chromium/browser.go @@ -227,6 +227,7 @@ func (b *chromiumBrowser) pdf(ctx context.Context, logger *zap.Logger, url, outp clearCookiesActionFunc(logger, b.arguments.clearCookies), disableJavaScriptActionFunc(logger, b.arguments.disableJavaScript), setCookiesActionFunc(logger, options.Cookies), + userAgentOverride(logger, options.UserAgent), extraHttpHeadersActionFunc(logger, options.ExtraHttpHeaders), navigateActionFunc(logger, url, options.SkipNetworkIdleEvent), hideDefaultWhiteBackgroundActionFunc(logger, options.OmitBackground, options.PrintBackground), @@ -250,6 +251,7 @@ func (b *chromiumBrowser) screenshot(ctx context.Context, logger *zap.Logger, ur clearCookiesActionFunc(logger, b.arguments.clearCookies), disableJavaScriptActionFunc(logger, b.arguments.disableJavaScript), setCookiesActionFunc(logger, options.Cookies), + userAgentOverride(logger, options.UserAgent), extraHttpHeadersActionFunc(logger, options.ExtraHttpHeaders), navigateActionFunc(logger, url, options.SkipNetworkIdleEvent), hideDefaultWhiteBackgroundActionFunc(logger, options.OmitBackground, true), diff --git a/pkg/modules/chromium/browser_test.go b/pkg/modules/chromium/browser_test.go index 4591f7b3..84efcadf 100644 --- a/pkg/modules/chromium/browser_test.go +++ b/pkg/modules/chromium/browser_test.go @@ -614,6 +614,41 @@ func TestChromiumBrowser_pdf(t *testing.T) { "set cookie", }, }, + { + scenario: "user agent override", + browser: newChromiumBrowser( + browserArguments{ + binPath: os.Getenv("CHROMIUM_BIN_PATH"), + wsUrlReadTimeout: 5 * time.Second, + allowList: regexp2.MustCompile("", 0), + denyList: regexp2.MustCompile("", 0), + }, + ), + fs: func() *gotenberg.FileSystem { + fs := gotenberg.NewFileSystem() + + err := os.MkdirAll(fs.WorkingDirPath(), 0o755) + if err != nil { + t.Fatalf(fmt.Sprintf("expected no error but got: %v", err)) + } + + err = os.WriteFile(fmt.Sprintf("%s/index.html", fs.WorkingDirPath()), []byte("

User-Agent override

"), 0o755) + if err != nil { + t.Fatalf("expected no error but got: %v", err) + } + + return fs + }(), + options: PdfOptions{ + Options: Options{UserAgent: "foo"}, + }, + noDeadline: false, + start: true, + expectError: false, + expectedLogEntries: []string{ + fmt.Sprintf("user agent override: foo"), + }, + }, { scenario: "extra HTTP headers", browser: newChromiumBrowser( @@ -1990,6 +2025,7 @@ func TestChromiumBrowser_screenshot(t *testing.T) { "cache not cleared", "cookies not cleared", "JavaScript not disabled", + "no user agent override", "no extra HTTP headers", "navigate to", "default white background not hidden", @@ -2037,6 +2073,7 @@ func TestChromiumBrowser_screenshot(t *testing.T) { "cookies not cleared", "JavaScript not disabled", "no cookies to set", + "no user agent override", "no extra HTTP headers", "navigate to", "default white background not hidden", @@ -2084,6 +2121,7 @@ func TestChromiumBrowser_screenshot(t *testing.T) { "cookies not cleared", "JavaScript not disabled", "no cookies to set", + "no user agent override", "no extra HTTP headers", "navigate to", "default white background not hidden", diff --git a/pkg/modules/chromium/chromium.go b/pkg/modules/chromium/chromium.go index cbf96181..374dd3bd 100644 --- a/pkg/modules/chromium/chromium.go +++ b/pkg/modules/chromium/chromium.go @@ -108,8 +108,12 @@ type Options struct { // Optional Cookies []Cookie - // ExtraHttpHeaders are the HTTP headers to send by Chromium while loading - // the HTML document. + // UserAgent overrides the default 'User-Agent' HTTP header. + // Optional. + UserAgent string + + // ExtraHttpHeaders are extra HTTP headers to send by Chromium while + // loading he HTML document. // Optional. ExtraHttpHeaders map[string]string @@ -134,6 +138,7 @@ func DefaultOptions() Options { WaitWindowStatus: "", WaitForExpression: "", Cookies: nil, + UserAgent: "", ExtraHttpHeaders: nil, EmulatedMediaType: "", OmitBackground: false, diff --git a/pkg/modules/chromium/routes.go b/pkg/modules/chromium/routes.go index a0436540..3ee8d647 100644 --- a/pkg/modules/chromium/routes.go +++ b/pkg/modules/chromium/routes.go @@ -35,6 +35,7 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) { waitWindowStatus string waitForExpression string cookies []Cookie + userAgent string extraHttpHeaders map[string]string emulatedMediaType string omitBackground bool @@ -78,6 +79,7 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) { return err }). + String("userAgent", &userAgent, defaultOptions.UserAgent). Custom("extraHttpHeaders", func(value string) error { if value == "" { extraHttpHeaders = defaultOptions.ExtraHttpHeaders @@ -115,6 +117,7 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) { WaitWindowStatus: waitWindowStatus, WaitForExpression: waitForExpression, Cookies: cookies, + UserAgent: userAgent, ExtraHttpHeaders: extraHttpHeaders, EmulatedMediaType: emulatedMediaType, OmitBackground: omitBackground, diff --git a/pkg/modules/chromium/tasks.go b/pkg/modules/chromium/tasks.go index 2c593da6..ac5d6e19 100644 --- a/pkg/modules/chromium/tasks.go +++ b/pkg/modules/chromium/tasks.go @@ -281,6 +281,23 @@ func setCookiesActionFunc(logger *zap.Logger, cookies []Cookie) chromedp.ActionF } } +func userAgentOverride(logger *zap.Logger, userAgent string) chromedp.ActionFunc { + return func(ctx context.Context) error { + if len(userAgent) == 0 { + logger.Debug("no user agent override") + return nil + } + + logger.Debug(fmt.Sprintf("user agent override: %s", userAgent)) + err := emulation.SetUserAgentOverride(userAgent).Do(ctx) + if err == nil { + return nil + } + + return fmt.Errorf("set user agent override: %w", err) + } +} + func extraHttpHeadersActionFunc(logger *zap.Logger, extraHttpHeaders map[string]string) chromedp.ActionFunc { return func(ctx context.Context) error { if len(extraHttpHeaders) == 0 {