mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-17 20:52:14 +01:00
fix(chromium): bound the total scope matching time per conversion
This commit is contained in:
52
pkg/modules/chromium/scopebudget.go
Normal file
52
pkg/modules/chromium/scopebudget.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package chromium
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// scopeMatchBudgetPerConversion caps the total time a single conversion may
|
||||
// spend matching scoped extra HTTP header patterns.
|
||||
//
|
||||
// The per-pattern MatchTimeout bounds one match, not their number: Chromium
|
||||
// pauses every sub-resource request, and each paused request is matched against
|
||||
// every scoped header. Without a shared budget the total is the product of the
|
||||
// two, both of which the client controls.
|
||||
// See https://github.com/gotenberg/gotenberg/issues/1588.
|
||||
const scopeMatchBudgetPerConversion = 5 * time.Second
|
||||
|
||||
// scopeMatchBudget is a time allowance shared by every scope match of a
|
||||
// conversion. It is safe for concurrent use: paused requests are handled on
|
||||
// their own goroutines.
|
||||
type scopeMatchBudget struct {
|
||||
remaining atomic.Int64
|
||||
}
|
||||
|
||||
// newScopeMatchBudget returns a [scopeMatchBudget] allowing d of matching.
|
||||
func newScopeMatchBudget(d time.Duration) *scopeMatchBudget {
|
||||
b := new(scopeMatchBudget)
|
||||
b.remaining.Store(int64(d))
|
||||
return b
|
||||
}
|
||||
|
||||
// tryAcquire reports whether the budget still allows a match.
|
||||
func (b *scopeMatchBudget) tryAcquire() bool {
|
||||
return b.remaining.Load() > 0
|
||||
}
|
||||
|
||||
// consume subtracts the time a match took. It saturates at zero so that a long
|
||||
// match cannot wrap the counter back into credit.
|
||||
func (b *scopeMatchBudget) consume(d time.Duration) {
|
||||
for {
|
||||
current := b.remaining.Load()
|
||||
if current <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
next := max(current-int64(d), 0)
|
||||
|
||||
if b.remaining.CompareAndSwap(current, next) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user