mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-08 00:22:14 +01:00
feat(chromium): add support for emulated media features in Chromium (#1474)
Closes https://github.com/gotenberg/gotenberg/issues/1460 It can be easier to print a "clean" PDF of some pages if you emulate media features like `prefers-reduced-motion`. Add support for that emulation.
This commit is contained in:
@@ -288,7 +288,7 @@ func (b *chromiumBrowser) pdf(ctx context.Context, logger *zap.Logger, url, outp
|
|||||||
navigateActionFunc(logger, url, options.SkipNetworkIdleEvent),
|
navigateActionFunc(logger, url, options.SkipNetworkIdleEvent),
|
||||||
hideDefaultWhiteBackgroundActionFunc(logger, options.OmitBackground, options.PrintBackground),
|
hideDefaultWhiteBackgroundActionFunc(logger, options.OmitBackground, options.PrintBackground),
|
||||||
forceExactColorsActionFunc(logger, options.PrintBackground),
|
forceExactColorsActionFunc(logger, options.PrintBackground),
|
||||||
emulateMediaTypeActionFunc(logger, options.EmulatedMediaType),
|
emulateMediaTypeActionFunc(logger, options.EmulatedMediaType, options.EmulatedMediaFeatures),
|
||||||
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
||||||
waitForSelectorVisibleBeforePrintActionFunc(logger, options.WaitForSelector),
|
waitForSelectorVisibleBeforePrintActionFunc(logger, options.WaitForSelector),
|
||||||
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
||||||
@@ -314,7 +314,7 @@ func (b *chromiumBrowser) screenshot(ctx context.Context, logger *zap.Logger, ur
|
|||||||
navigateActionFunc(logger, url, options.SkipNetworkIdleEvent),
|
navigateActionFunc(logger, url, options.SkipNetworkIdleEvent),
|
||||||
hideDefaultWhiteBackgroundActionFunc(logger, options.OmitBackground, true),
|
hideDefaultWhiteBackgroundActionFunc(logger, options.OmitBackground, true),
|
||||||
forceExactColorsActionFunc(logger, true),
|
forceExactColorsActionFunc(logger, true),
|
||||||
emulateMediaTypeActionFunc(logger, options.EmulatedMediaType),
|
emulateMediaTypeActionFunc(logger, options.EmulatedMediaType, options.EmulatedMediaFeatures),
|
||||||
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
waitForExpressionBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitForExpression),
|
||||||
waitForSelectorVisibleBeforePrintActionFunc(logger, options.WaitForSelector),
|
waitForSelectorVisibleBeforePrintActionFunc(logger, options.WaitForSelector),
|
||||||
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
|
||||||
|
|||||||
@@ -165,11 +165,28 @@ type Options struct {
|
|||||||
// "print".
|
// "print".
|
||||||
EmulatedMediaType string
|
EmulatedMediaType string
|
||||||
|
|
||||||
|
// EmulatedMediaFeatures are the media features to emulate, e.g.,
|
||||||
|
// [{"name": "prefers-color-scheme", "value": "dark"}].
|
||||||
|
EmulatedMediaFeatures []EmulatedMediaFeature
|
||||||
|
|
||||||
// OmitBackground hides the default white background and allows generating
|
// OmitBackground hides the default white background and allows generating
|
||||||
// PDFs with transparency.
|
// PDFs with transparency.
|
||||||
OmitBackground bool
|
OmitBackground bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmulatedMediaFeature gathers the available entries for emulating a media
|
||||||
|
// feature.
|
||||||
|
type EmulatedMediaFeature struct {
|
||||||
|
// Name is the media feature name (e.g., "prefers-color-scheme",
|
||||||
|
// "prefers-reduced-motion").
|
||||||
|
// Required.
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Value is the media feature value (e.g., "dark", "reduce").
|
||||||
|
// Required.
|
||||||
|
Value string `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultOptions returns the default values for Options.
|
// DefaultOptions returns the default values for Options.
|
||||||
func DefaultOptions() Options {
|
func DefaultOptions() Options {
|
||||||
return Options{
|
return Options{
|
||||||
@@ -187,6 +204,7 @@ func DefaultOptions() Options {
|
|||||||
UserAgent: "",
|
UserAgent: "",
|
||||||
ExtraHttpHeaders: nil,
|
ExtraHttpHeaders: nil,
|
||||||
EmulatedMediaType: "",
|
EmulatedMediaType: "",
|
||||||
|
EmulatedMediaFeatures: nil,
|
||||||
OmitBackground: false,
|
OmitBackground: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ var sameSiteRegexp = regexp2.MustCompile(
|
|||||||
// - ignoreResourceHttpStatusDomains: []string
|
// - ignoreResourceHttpStatusDomains: []string
|
||||||
// - cookies: []Cookie
|
// - cookies: []Cookie
|
||||||
// - extraHttpHeaders: map[string]string
|
// - extraHttpHeaders: map[string]string
|
||||||
|
// - emulatedMediaFeatures: map[string]string
|
||||||
//
|
//
|
||||||
// Domain filtering only applies to resource checks triggered by
|
// Domain filtering only applies to resource checks triggered by
|
||||||
// "failOnResourceHttpStatusCodes".
|
// "failOnResourceHttpStatusCodes".
|
||||||
@@ -60,6 +61,7 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
|||||||
userAgent string
|
userAgent string
|
||||||
extraHttpHeaders []ExtraHttpHeader
|
extraHttpHeaders []ExtraHttpHeader
|
||||||
emulatedMediaType string
|
emulatedMediaType string
|
||||||
|
emulatedMediaFeatures []EmulatedMediaFeature
|
||||||
omitBackground bool
|
omitBackground bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -227,6 +229,27 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}).
|
}).
|
||||||
|
Custom("emulatedMediaFeatures", func(value string) error {
|
||||||
|
if value == "" {
|
||||||
|
emulatedMediaFeatures = defaultOptions.EmulatedMediaFeatures
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var features map[string]string
|
||||||
|
err := json.Unmarshal([]byte(value), &features)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal emulatedMediaFeatures: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range features {
|
||||||
|
emulatedMediaFeatures = append(emulatedMediaFeatures, EmulatedMediaFeature{
|
||||||
|
Name: k,
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}).
|
||||||
Bool("omitBackground", &omitBackground, defaultOptions.OmitBackground)
|
Bool("omitBackground", &omitBackground, defaultOptions.OmitBackground)
|
||||||
|
|
||||||
options := Options{
|
options := Options{
|
||||||
@@ -244,6 +267,7 @@ func FormDataChromiumOptions(ctx *api.Context) (*api.FormData, Options) {
|
|||||||
UserAgent: userAgent,
|
UserAgent: userAgent,
|
||||||
ExtraHttpHeaders: extraHttpHeaders,
|
ExtraHttpHeaders: extraHttpHeaders,
|
||||||
EmulatedMediaType: emulatedMediaType,
|
EmulatedMediaType: emulatedMediaType,
|
||||||
|
EmulatedMediaFeatures: emulatedMediaFeatures,
|
||||||
OmitBackground: omitBackground,
|
OmitBackground: omitBackground,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -423,26 +423,44 @@ func forceExactColorsActionFunc(logger *zap.Logger, printBackground bool) chrome
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func emulateMediaTypeActionFunc(logger *zap.Logger, mediaType string) chromedp.ActionFunc {
|
func emulateMediaTypeActionFunc(logger *zap.Logger, mediaType string, mediaFeatures []EmulatedMediaFeature) chromedp.ActionFunc {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
if mediaType == "" {
|
if mediaType == "" && len(mediaFeatures) == 0 {
|
||||||
logger.Debug("no emulated media type")
|
logger.Debug("no emulated media type or features")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if mediaType != "screen" && mediaType != "print" {
|
if mediaType != "" && mediaType != "screen" && mediaType != "print" {
|
||||||
return fmt.Errorf("validate emulated media type '%s': %w", mediaType, ErrInvalidEmulatedMediaType)
|
return fmt.Errorf("validate emulated media type '%s': %w", mediaType, ErrInvalidEmulatedMediaType)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug(fmt.Sprintf("emulate media type '%s'", mediaType))
|
|
||||||
|
|
||||||
emulatedMedia := emulation.SetEmulatedMedia()
|
emulatedMedia := emulation.SetEmulatedMedia()
|
||||||
err := emulatedMedia.WithMedia(mediaType).Do(ctx)
|
|
||||||
|
if mediaType != "" {
|
||||||
|
logger.Debug(fmt.Sprintf("emulate media type '%s'", mediaType))
|
||||||
|
emulatedMedia = emulatedMedia.WithMedia(mediaType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mediaFeatures) > 0 {
|
||||||
|
logger.Debug(fmt.Sprintf("emulate media features %+v", mediaFeatures))
|
||||||
|
|
||||||
|
features := make([]*emulation.MediaFeature, len(mediaFeatures))
|
||||||
|
for i, f := range mediaFeatures {
|
||||||
|
features[i] = &emulation.MediaFeature{
|
||||||
|
Name: f.Name,
|
||||||
|
Value: f.Value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emulatedMedia = emulatedMedia.WithFeatures(features)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := emulatedMedia.Do(ctx)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("emulate media type '%s': %w", mediaType, err)
|
return fmt.Errorf("emulate media: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -281,6 +281,82 @@ Feature: /forms/chromium/convert/html
|
|||||||
Emulated media type is 'print'.
|
Emulated media type is 'print'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Scenario: POST /forms/chromium/convert/html (Emulated Media Features)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/feature-rich-html/index.html | file |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should NOT have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/feature-rich-html/index.html | file |
|
||||||
|
| emulatedMediaFeatures | {"prefers-reduced-motion":"reduce"} | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/feature-rich-html/index.html | file |
|
||||||
|
| emulatedMediaType | screen | field |
|
||||||
|
| emulatedMediaFeatures | {"prefers-reduced-motion":"reduce"} | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'screen'.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should NOT have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'print'.
|
||||||
|
"""
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/feature-rich-html/index.html | file |
|
||||||
|
| emulatedMediaType | print | field |
|
||||||
|
| emulatedMediaFeatures | {"prefers-reduced-motion":"reduce"} | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'print'.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should NOT have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'screen'.
|
||||||
|
"""
|
||||||
|
|
||||||
Scenario: POST /forms/chromium/convert/html (Default Allow / Deny Lists)
|
Scenario: POST /forms/chromium/convert/html (Default Allow / Deny Lists)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
@@ -550,6 +626,15 @@ Feature: /forms/chromium/convert/html
|
|||||||
"""
|
"""
|
||||||
Invalid form data: form field 'extraHttpHeaders' is invalid (got '{"foo":"bar;scope=*."}', resulting to invalid scope regex pattern for header 'foo': error parsing regexp: missing argument to repetition operator in `*.`)
|
Invalid form data: form field 'extraHttpHeaders' is invalid (got '{"foo":"bar;scope=*."}', resulting to invalid scope regex pattern for header 'foo': error parsing regexp: missing argument to repetition operator in `*.`)
|
||||||
"""
|
"""
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
|
| files | testdata/page-1-html/index.html | file |
|
||||||
|
| emulatedMediaFeatures | foo | field |
|
||||||
|
Then the response status code should be 400
|
||||||
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
|
Then the response body should match string:
|
||||||
|
"""
|
||||||
|
Invalid form data: form field 'emulatedMediaFeatures' is invalid (got 'foo', resulting to unmarshal emulatedMediaFeatures: invalid character 'o' in literal false (expecting 'a'))
|
||||||
|
"""
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/html" endpoint with the following form data and header(s):
|
||||||
| files | testdata/page-1-html/index.html | file |
|
| files | testdata/page-1-html/index.html | file |
|
||||||
| splitMode | foo | field |
|
| splitMode | foo | field |
|
||||||
|
|||||||
@@ -346,6 +346,86 @@ Feature: /forms/chromium/convert/url
|
|||||||
Emulated media type is 'print'.
|
Emulated media type is 'print'.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Scenario: POST /forms/chromium/convert/url (Emulated Media Features)
|
||||||
|
Given I have a default Gotenberg container
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/feature-rich-html-remote/index.html | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should NOT have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/feature-rich-html-remote/index.html | field |
|
||||||
|
| emulatedMediaFeatures | {"prefers-reduced-motion":"reduce"} | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/feature-rich-html-remote/index.html | field |
|
||||||
|
| emulatedMediaType | screen | field |
|
||||||
|
| emulatedMediaFeatures | {"prefers-reduced-motion":"reduce"} | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'screen'.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should NOT have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'print'.
|
||||||
|
"""
|
||||||
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/feature-rich-html-remote/index.html | field |
|
||||||
|
| emulatedMediaType | print | field |
|
||||||
|
| emulatedMediaFeatures | {"prefers-reduced-motion":"reduce"} | field |
|
||||||
|
| Gotenberg-Output-Filename | foo | header |
|
||||||
|
Then the response status code should be 200
|
||||||
|
Then the response header "Content-Type" should be "application/pdf"
|
||||||
|
Then there should be 1 PDF(s) in the response
|
||||||
|
Then there should be the following file(s) in the response:
|
||||||
|
| foo.pdf |
|
||||||
|
Then the "foo.pdf" PDF should have 1 page(s)
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'print'.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Prefers reduced motion.
|
||||||
|
"""
|
||||||
|
Then the "foo.pdf" PDF should NOT have the following content at page 1:
|
||||||
|
"""
|
||||||
|
Emulated media type is 'screen'.
|
||||||
|
"""
|
||||||
|
|
||||||
Scenario: POST /forms/chromium/convert/url (Default Allow / Deny Lists)
|
Scenario: POST /forms/chromium/convert/url (Default Allow / Deny Lists)
|
||||||
Given I have a default Gotenberg container
|
Given I have a default Gotenberg container
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
@@ -627,6 +707,16 @@ Feature: /forms/chromium/convert/url
|
|||||||
Invalid form data: form field 'extraHttpHeaders' is invalid (got '{"foo":"bar;scope=*."}', resulting to invalid scope regex pattern for header 'foo': error parsing regexp: missing argument to repetition operator in `*.`)
|
Invalid form data: form field 'extraHttpHeaders' is invalid (got '{"foo":"bar;scope=*."}', resulting to invalid scope regex pattern for header 'foo': error parsing regexp: missing argument to repetition operator in `*.`)
|
||||||
"""
|
"""
|
||||||
Given I have a static server
|
Given I have a static server
|
||||||
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
|
| url | http://host.docker.internal:%d/html/testdata/page-1-html/index.html | field |
|
||||||
|
| emulatedMediaFeatures | foo | field |
|
||||||
|
Then the response status code should be 400
|
||||||
|
Then the response header "Content-Type" should be "text/plain; charset=UTF-8"
|
||||||
|
Then the response body should match string:
|
||||||
|
"""
|
||||||
|
Invalid form data: form field 'emulatedMediaFeatures' is invalid (got 'foo', resulting to unmarshal emulatedMediaFeatures: invalid character 'o' in literal false (expecting 'a'))
|
||||||
|
"""
|
||||||
|
Given I have a static server
|
||||||
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
When I make a "POST" request to Gotenberg at the "/forms/chromium/convert/url" endpoint with the following form data and header(s):
|
||||||
| url | http://host.docker.internal:%d/html/testdata/page-1-html/index.html | field |
|
| url | http://host.docker.internal:%d/html/testdata/page-1-html/index.html | field |
|
||||||
| splitMode | foo | field |
|
| splitMode | foo | field |
|
||||||
|
|||||||
@@ -20,6 +20,14 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#reduced-motion {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
#reduced-motion {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -29,6 +37,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p id="print">Emulated media type is 'print'.</p>
|
<p id="print">Emulated media type is 'print'.</p>
|
||||||
<p id="screen">Emulated media type is 'screen'.</p>
|
<p id="screen">Emulated media type is 'screen'.</p>
|
||||||
|
<p id="reduced-motion">Prefers reduced motion.</p>
|
||||||
<p id="javascript" style="display: none">JavaScript is enabled.</p>
|
<p id="javascript" style="display: none">JavaScript is enabled.</p>
|
||||||
<iframe src="file:///etc/passwd"></iframe>
|
<iframe src="file:///etc/passwd"></iframe>
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,14 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#reduced-motion {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
#reduced-motion {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -37,6 +45,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p id="print">Emulated media type is 'print'.</p>
|
<p id="print">Emulated media type is 'print'.</p>
|
||||||
<p id="screen">Emulated media type is 'screen'.</p>
|
<p id="screen">Emulated media type is 'screen'.</p>
|
||||||
|
<p id="reduced-motion">Prefers reduced motion.</p>
|
||||||
<p id="javascript" style="display: none">JavaScript is enabled.</p>
|
<p id="javascript" style="display: none">JavaScript is enabled.</p>
|
||||||
<iframe src="/etc/passwd"></iframe>
|
<iframe src="/etc/passwd"></iframe>
|
||||||
<iframe src="\\localhost/etc/passwd"></iframe>
|
<iframe src="\\localhost/etc/passwd"></iframe>
|
||||||
|
|||||||
Reference in New Issue
Block a user