mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-17 20:52:14 +01:00
feat(chromium): add IgnoreResourceHttpStatusDomains option to filter out resources based on their hostnames (#1434)
* Introduced `IgnoreResourceHttpStatusDomains` option to filter out resources based on their hostnames - Introduced `IgnoreResourceHttpStatusDomains` option to filter out resources based on their hostnames during HTTP status code checks. - Updated relevant functions to handle domain normalization and matching. - Enhanced the form data handling to include the new option. - Added integration test scenario to verify the functionality of ignoring specified domains. * Updated the `normalizeDomains` function to initialize the `normalized` slice with a predefined capacity based on the input `domains` slice length, improving memory allocation efficiency.
This commit is contained in:
@@ -4,7 +4,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/chromedp/cdproto/cdp"
|
||||
@@ -143,6 +145,7 @@ type eventResponseReceivedOptions struct {
|
||||
invalidHttpStatusCode *error
|
||||
invalidHttpStatusCodeMu *sync.RWMutex
|
||||
failOnResourceOnHttpStatusCode []int64
|
||||
ignoreResourceHttpStatusDomains []string
|
||||
invalidResourceHttpStatusCode *error
|
||||
invalidResourceHttpStatusCodeMu *sync.RWMutex
|
||||
}
|
||||
@@ -157,6 +160,8 @@ func listenForEventResponseReceived(
|
||||
logger *zap.Logger,
|
||||
options eventResponseReceivedOptions,
|
||||
) {
|
||||
normalizedIgnoreDomains := normalizeDomains(options.ignoreResourceHttpStatusDomains)
|
||||
|
||||
for _, code := range []int64{199, 299, 399, 499, 599} {
|
||||
if slices.Contains(options.failOnHttpStatusCodes, code) {
|
||||
for i := code - 99; i <= code; i++ {
|
||||
@@ -190,6 +195,11 @@ func listenForEventResponseReceived(
|
||||
logger.Debug(fmt.Sprintf("event EventResponseReceived fired for a resource: %+v", ev.Response))
|
||||
|
||||
if slices.Contains(options.failOnResourceOnHttpStatusCode, ev.Response.Status) {
|
||||
if !shouldCheckResourceHttpStatusCode(ev.Response.URL, normalizedIgnoreDomains) {
|
||||
logger.Debug(fmt.Sprintf("skip resource HTTP status code check for '%s' due to domain filtering", ev.Response.URL))
|
||||
return
|
||||
}
|
||||
|
||||
options.invalidResourceHttpStatusCodeMu.Lock()
|
||||
defer options.invalidResourceHttpStatusCodeMu.Unlock()
|
||||
|
||||
@@ -202,6 +212,79 @@ func listenForEventResponseReceived(
|
||||
})
|
||||
}
|
||||
|
||||
func shouldCheckResourceHttpStatusCode(rawURL string, ignoreDomains []string) bool {
|
||||
host := hostnameFromURL(rawURL)
|
||||
|
||||
if len(ignoreDomains) > 0 && matchesAnyDomain(host, ignoreDomains) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func hostnameFromURL(rawURL string) string {
|
||||
u, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.ToLower(u.Hostname())
|
||||
}
|
||||
|
||||
func normalizeDomains(domains []string) []string {
|
||||
normalized := make([]string, 0, len(domains))
|
||||
|
||||
for _, domain := range domains {
|
||||
d := normalizeDomain(domain)
|
||||
if d == "" {
|
||||
continue
|
||||
}
|
||||
normalized = append(normalized, d)
|
||||
}
|
||||
|
||||
return normalized
|
||||
}
|
||||
|
||||
func normalizeDomain(domain string) string {
|
||||
d := strings.ToLower(strings.TrimSpace(domain))
|
||||
if d == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Accept "example.com", "*.example.com", ".example.com", "https://example.com/path",
|
||||
// or "example.com:443".
|
||||
if strings.Contains(d, "://") || strings.HasPrefix(d, "//") {
|
||||
u, err := url.Parse(d)
|
||||
if err == nil && u.Hostname() != "" {
|
||||
d = strings.ToLower(u.Hostname())
|
||||
}
|
||||
} else {
|
||||
// Make it parseable as a URL to extract the hostname and drop any port/path.
|
||||
u, err := url.Parse("https://" + d)
|
||||
if err == nil && u.Hostname() != "" {
|
||||
d = strings.ToLower(u.Hostname())
|
||||
}
|
||||
}
|
||||
|
||||
d = strings.TrimPrefix(d, "*.")
|
||||
d = strings.TrimPrefix(d, ".")
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func matchesAnyDomain(host string, domains []string) bool {
|
||||
if host == "" || len(domains) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, domain := range domains {
|
||||
if host == domain || strings.HasSuffix(host, "."+domain) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type eventLoadingFailedOptions struct {
|
||||
loadingFailed *error
|
||||
loadingFailedMu *sync.RWMutex
|
||||
|
||||
Reference in New Issue
Block a user