-
Notifications
You must be signed in to change notification settings - Fork 758
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
limit the size of the uids cookie #1004
Conversation
usersync/cookie.go
Outdated
@@ -162,9 +215,31 @@ func (cookie *PBSCookie) GetId(bidderName openrtb_ext.BidderName) (id string, ex | |||
// SetCookieOnResponse is a shortcut for "ToHTTPCookie(); cookie.setDomain(domain); setCookie(w, cookie)" | |||
func (cookie *PBSCookie) SetCookieOnResponse(w http.ResponseWriter, domain string, ttl time.Duration) { | |||
httpCookie := cookie.ToHTTPCookie(ttl) | |||
var MAX_COOKIE_SIZE int = 1 << 15 // 32 KB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will want this as a config parameter rather than hardcoded. Also a check for a 0 "size" to disable enforcement of a maximum size may not be bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean get it from the configmap.yaml
file itself? Bring it all the way here straight from the Configuration struct
found in config/config.go
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean check for a 0 size? A 0 size httpCookie.String()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, bring the config struct, or the relevant value, all the way down to here. It is the configured value for MAX_COOKIE_SIZE
you should check for a 0 value, as a method of turning off this feature. If a host limits the number of bidders they support, they can limit the size the cookie can grow to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
usersync/cookie.go
Outdated
var oldestElem string = "" | ||
var oldestDate int64 = math.MaxInt64 | ||
for key, value := range cookie.uids { | ||
var timeSince time.Duration = now.Sub(value.Expires) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't need to specify time.Duration
as that is already defined as the return type of now.Sub()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, since you are taking the current time, and subtracting the expirery time, this will result in a negative number. The most negative number will be the expires time that is furthest from now, so in the end we will remove the entry that has the longest time before it expires.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gosh, I got the Sub()
function backwards, corrected
config/config.go
Outdated
CacheURL Cache `mapstructure:"cache"` | ||
RecaptchaSecret string `mapstructure:"recaptcha_secret"` | ||
HostCookie HostCookie `mapstructure:"host_cookie"` | ||
MaxCookieSizeBytes int `mapstructure:"max_cookie_size_bytes"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have a Max Size here as well as in HostCookie
. I think HostCookie
is probably the best place for it out of the two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, that's a leftover from another approach I was trying. Good call. Removed
config/config.go
Outdated
@@ -500,6 +502,7 @@ func SetupViper(v *viper.Viper, filename string) { | |||
v.SetDefault("host_cookie.optout_cookie.name", "") | |||
v.SetDefault("host_cookie.value", "") | |||
v.SetDefault("host_cookie.ttl_days", 90) | |||
v.SetDefault("host_cookie.max_cookie_size_bytes", 32768) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably want to set the default as unlimited, so it won't change the behavior of running installs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
usersync/cookie.go
Outdated
var oldestElem string = "" | ||
var oldestDate int64 = math.MaxInt64 | ||
for key, value := range cookie.uids { | ||
timeUntilExpiration := value.Expires.Sub(now) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a tip: Time package has an until
function that will do exactly this for you. So you can potentially replace this with time.Until(value.Expires)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
usersync/cookie.go
Outdated
uids map[string]uidWithExpiry | ||
optOut bool | ||
birthday *time.Time | ||
maxSizeBytes int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need maxSizeBytes
as part of the PBSCookie
struct. We can just access the MaxCookieSizeBytes
in the HostCookie
struct and pass it on in the call to SetCookieOnResponse
. This should make the code a little simpler.
Spoke with @guscarreon offline about this and he said he will make the suggested change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
config/config.go
Outdated
// If a non-zero-less-than-500-byte "host_cookie.max_cookie_size_bytes" value was specified in the | ||
// environment configuration of prebid-server, default to 500 bytes | ||
if maxCookieSize != 0 && maxCookieSize < MIN_COOKIE_SIZE_BYTES { | ||
return errors.New("Configured cookie size is less than allowed minimum size") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be good to incorporate the MIN_COOKIE_SIZE_BYTES
value in the error message so that the user knows what it is from the error message itself rather than having to dig into the code to find it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes perfect sense, done
usersync/cookie_test.go
Outdated
} | ||
|
||
func newBigCookie() (*PBSCookie, int) { | ||
var bigCookie *PBSCookie = &PBSCookie{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about creating a test folder and adding these different cookies there in .json
files and then using those in the tests rather than populating this test file with a giant map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spoke with @guscarreon about this and we probably don't need this particular test case to start with and so he's gonna evaluate and remove this if not needed.
…ase in usersync/cookie_test.go
usersync/cookie_test.go
Outdated
assert.Equal(t, cookieToSendLen, len(processedCookie.uids), "[Test %d] MaxCookieSizeBytes equal to zero or bigger than %d bytes should be snough to set and remain cookie unchanged \n", i+1, len(processedCookie.uids)) | ||
_, oldestFound := processedCookie.uids["key7"] | ||
assert.Equal(t, cookieToSendLen, len(processedCookie.uids), "[Test %d] MaxCookieSizeBytes equal to zero or bigger than %d bytes should be enough to set and remain cookie unchanged \n", i+1, len(processedCookie.uids)) | ||
_, oldestFound := processedCookie.uids[closestToExpirationDate] | ||
assert.Equal(t, oldestFound, true, "[Test %d] Oldest entry in cookie should not have been eliminated", i+1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just do assert.Contains
here on the map and skip the previous line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
usersync/cookie_test.go
Outdated
assert.Equal(t, oldestFound, true, "[Test %d] Oldest entry in cookie should not have been eliminated", i+1) | ||
case "trim": | ||
assert.Equal(t, cookieToSendLen > len(processedCookie.uids), true, "[Test %d] MaxCookieSizeBytes of %d is smaller than %d bytes and cookie entries should have been removed\n", i+1, testCases[i].maxCookieSize, cookieToSendLen) | ||
_, oldestFound := processedCookie.uids["key7"] | ||
_, oldestFound := processedCookie.uids[closestToExpirationDate] | ||
assert.Equal(t, oldestFound, false, "[Test %d] Oldest entry in cookie was not eliminated", i+1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
* some research * Modifications and test cases in place * Hans' corrections and random expiration date to cookies in test case * Cookie size gets defined in configmap.yaml now * removed MaxCookieSizeBytes duplicate * removed unnecessary constant declaration * Set unlimited size as default, added unlimited size test case * corrected test case * symplified solution by pulling size from Configuration struct itself * substituted time.Sub() for time.Until() and tuned adapter test cases * removed vim .swp files * MIN_COOKIE_SIZE_BYTES implemented in config.go * correct SetCookieOnResponse() return value * Printed MIN_COOKIE_SIZE_BYTES in error message, added one more test case in usersync/cookie_test.go * Resolved conflict in config/config.go * Resolved another conflict
* some research * Modifications and test cases in place * Hans' corrections and random expiration date to cookies in test case * Cookie size gets defined in configmap.yaml now * removed MaxCookieSizeBytes duplicate * removed unnecessary constant declaration * Set unlimited size as default, added unlimited size test case * corrected test case * symplified solution by pulling size from Configuration struct itself * substituted time.Sub() for time.Until() and tuned adapter test cases * removed vim .swp files * MIN_COOKIE_SIZE_BYTES implemented in config.go * correct SetCookieOnResponse() return value * Printed MIN_COOKIE_SIZE_BYTES in error message, added one more test case in usersync/cookie_test.go * Resolved conflict in config/config.go * Resolved another conflict
* some research * Modifications and test cases in place * Hans' corrections and random expiration date to cookies in test case * Cookie size gets defined in configmap.yaml now * removed MaxCookieSizeBytes duplicate * removed unnecessary constant declaration * Set unlimited size as default, added unlimited size test case * corrected test case * symplified solution by pulling size from Configuration struct itself * substituted time.Sub() for time.Until() and tuned adapter test cases * removed vim .swp files * MIN_COOKIE_SIZE_BYTES implemented in config.go * correct SetCookieOnResponse() return value * Printed MIN_COOKIE_SIZE_BYTES in error message, added one more test case in usersync/cookie_test.go * Resolved conflict in config/config.go * Resolved another conflict
* some research * Modifications and test cases in place * Hans' corrections and random expiration date to cookies in test case * Cookie size gets defined in configmap.yaml now * removed MaxCookieSizeBytes duplicate * removed unnecessary constant declaration * Set unlimited size as default, added unlimited size test case * corrected test case * symplified solution by pulling size from Configuration struct itself * substituted time.Sub() for time.Until() and tuned adapter test cases * removed vim .swp files * MIN_COOKIE_SIZE_BYTES implemented in config.go * correct SetCookieOnResponse() return value * Printed MIN_COOKIE_SIZE_BYTES in error message, added one more test case in usersync/cookie_test.go * Resolved conflict in config/config.go * Resolved another conflict
We hit an issue where the header (containing the uids cookie) overran the limit that Ingress could handle. This pull request checks the size of the
PBSCookie
and, if found bigger than 32 KB in itshttp
form, traverses thePBSCookie.uids
field deleting the entries closest to expiration date.