-
Notifications
You must be signed in to change notification settings - Fork 762
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
Update to OpenRTB 2.6-202309 #3387
Conversation
@@ -147,7 +147,7 @@ func buildImpVideo(imp *openrtb2.Imp) error { | |||
} | |||
} | |||
|
|||
if imp.Video.H == 0 && imp.Video.W == 0 { | |||
if (imp.Video.H == nil || *imp.Video.H == 0) && (imp.Video.W == nil || *imp.Video.W == 0) { |
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.
Added nil checks before accessing the W and H fields.
Cadent: Should we remove the checks for 0 value now that nil is checked? .. aka, are you ok to receive a 0 value if it's explicitly provided in the request?
@@ -221,7 +221,7 @@ func getMediaTypeForImpID(impID string, imps []openrtb2.Imp) openrtb_ext.BidType | |||
} | |||
|
|||
func validateVideoParams(video *openrtb2.Video) (err error) { | |||
if video.W == 0 || video.H == 0 || video.MinDuration == 0 || video.MaxDuration == 0 || video.Placement == 0 || video.Linearity == 0 { | |||
if video.W == nil || *video.W == 0 || video.H == nil || *video.H == 0 || video.MinDuration == 0 || video.MaxDuration == 0 || video.Placement == 0 || video.Linearity == 0 { |
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.
Added nil checks before accessing the W and H fields.
Gumgum: Should a 0 value be considered an "invalid or missing" field now that it can represent nil if it's missing?
"c": 3 | ||
} | ||
} | ||
} |
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.
Removed unused variable.
@@ -103,9 +103,9 @@ const ( | |||
) | |||
|
|||
// NonBidObject is subset of Bid object with exact json signature | |||
// defined at https://github.com/prebid/openrtb/blob/v19.0.0/openrtb2/bid.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.
Removed url, since it will be hard to keep current.
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.
Added new pointer fields to existing Clone functions for OpenRTB objects. Cleaned up the BidderReq clone to now involve the request wrapper (this file is just for openrtb objects) and to make it's partial support clear. I'm guessing it's partial because that all we've needed so far?
if req.User != nil { | ||
userCopy := CloneUser(req.User) | ||
newReq.User = userCopy | ||
} |
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.
Removed duplicate nil checks.
assert.Equal(t, given, result, "equality") | ||
assert.NotSame(t, given, result, "pointer") | ||
}) | ||
} |
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.
Replaced with ptrutil.
videoCopy := *imp.Video | ||
videoCopy.W = ptrutil.ToPtr[int64](defaultVideoWidth) | ||
videoCopy.H = ptrutil.ToPtr[int64](defaultVideoHeight) | ||
imp.Video = &videoCopy |
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.
Beachfront: Fixed unprotected shared memory write. This code path previously had no test coverage.
"mimes": [ | ||
"video/mp4" | ||
], | ||
"w": 300 |
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.
Beachfront: What behavior would you like if one of the w or h values are nil / missing?
5, | ||
6 | ||
], | ||
"h": 480 |
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.
Cadent: What should the behavior be if just one size dimension is missing? Previous behavior would set the other one to 0.
@SyntaxNode |
func clear202309Fields(r *RequestWrapper) { | ||
r.ACat = nil | ||
|
||
for _, imp := range r.GetImp() { | ||
if audio := imp.Audio; audio != nil { | ||
audio.DurFloors = nil | ||
} | ||
|
||
if video := imp.Video; video != nil { | ||
video.DurFloors = nil | ||
} | ||
|
||
if pmp := imp.PMP; pmp != nil { | ||
for i := range pmp.Deals { | ||
pmp.Deals[i].Guar = 0 | ||
pmp.Deals[i].MinCPMPerSec = 0 | ||
pmp.Deals[i].DurFloors = nil | ||
} | ||
} | ||
} | ||
} |
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 think this function can be simplified slightly where we nil check the imp members directly instead of assigning them to a variable first.
func clear202309Fields(r *RequestWrapper) {
r.ACat = nil
for _, imp := range r.GetImp() {
if imp.Audio != nil {
imp.Audio.DurFloors = nil
}
if imp.Video != nil {
imp.Video.DurFloors = nil
}
if imp.PMP != nil {
for i := range imp.PMP.Deals {
imp.PMP.Deals[i].Guar = 0
imp.PMP.Deals[i].MinCPMPerSec = 0
imp.PMP.Deals[i].DurFloors = nil
}
}
}
}
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 had earlier versions of code written that way. I found that when the hierarchy gets deep the code is harder to follow. This is more evident in clear26Fields
. It might also be more efficient since the variable is only resolved once and reused - although admittedly the compiler may correct for that on its own.
Do you find the way you suggested to be easier to read?
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 do find my suggestion easier to read for me, but I have no issue keeping the function as it is.
Thank you 33across, beachfront, eplanning, and huaweiads for reviewing this PR. I did not hear from cadent_aperture, eplanning, gumgum, madvertise, richaudience, or smartadserver after including GitHub mentions and contacting their support email address. We'll proceed with this PR using our best judgement for the non response adapters. |
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.
When greping github.com\/prebid\/openrtb\/v19
two adapters that are still referencing v19
come up. They were probably merged recently:
$ grep -RnH 'github.com\/prebid\/openrtb\/v19' * 1 ↵
adapters/zmaticoo/zmaticoo.go:6: "github.com/prebid/openrtb/v19/openrtb2"
adapters/minutemedia/minutemedia.go:11: "github.com/prebid/openrtb/v19/openrtb2"
Can we please update?
seatBid.Bid[i].W = reqBid.Video.W | ||
seatBid.Bid[i].H = reqBid.Video.H | ||
seatBid.Bid[i].W = ptrutil.ValueOrDefault(reqBid.Video.W) | ||
seatBid.Bid[i].H = ptrutil.ValueOrDefault(reqBid.Video.H) |
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.
Nitpick: Line 110 above indicates that nil
and 0
values for W
and H
are filtered out. Should we simply dereference the pointer that we know is valid as a small optimization?
181
182 if bidType == "video" {
183 - seatBid.Bid[i].W = ptrutil.ValueOrDefault(reqBid.Video.W)
+ seatBid.Bid[i].W = *reqBid.Video.W
184 - seatBid.Bid[i].H = ptrutil.ValueOrDefault(reqBid.Video.H)
+ seatBid.Bid[i].H = *reqBid.Video.H
185 }
186
adapters/richaudience/richaudience.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.
Done.
bids[i].H = xtrnal.Imp[i].Video.H | ||
bids[i].W = xtrnal.Imp[i].Video.W | ||
bids[i].H = ptrutil.ValueOrDefault(xtrnal.Imp[i].Video.H) | ||
bids[i].W = ptrutil.ValueOrDefault(xtrnal.Imp[i].Video.W) |
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.
Function ValueOrDefault[T any](v *T)
might return 0
because that's the default value of the int64
type, but lines 479 to 494 above imply that defaultVideoWidth
and defaultVideoHeight
are prefered as default values instead. Should we modify to default to those constants?
682 for i := 0; i < len(bids); i++ {
683 crid := extractNurlVideoCrid(bids[i].NURL)
684
685 bids[i].CrID = crid
686 bids[i].ImpID = xtrnal.Imp[i].ID
687 - bids[i].H = ptrutil.ValueOrDefault(xtrnal.Imp[i].Video.H)
688 - bids[i].W = ptrutil.ValueOrDefault(xtrnal.Imp[i].Video.W)
+ // I know there's no ternary operator in Go. Wish there was
+ bids[i].H = (xtrnal.Imp[i].Video.H != nil && *xtrnal.Imp[i].Video.H > 0) ? *xtrnal.Imp[i].Video.H : defaultVideoHeight
+ bids[i].W = (xtrnal.Imp[i].Video.W != nil && *xtrnal.Imp[i].Video.W > 0) ? *xtrnal.Imp[i].Video.W : defaultVideoWidth
689 bids[i].ID = fmt.Sprintf("%sNurlVideo", xtrnal.Imp[i].ID)
690 }
691
adapters/beachfront/beachfront.go
Or, do lines 479 to 494 modified above, guarantee that xtrnal.Imp[i].Video.H
and xtrnal.Imp[i].Video.W
are already always set to defaultVideoWidth
and defaultVideoHeight
respectively and we just simply need to dereference here as we did in the RichAudience adapter? I honestly don't know this adapter's code enough to be perfectly sure.
682 for i := 0; i < len(bids); i++ {
683 crid := extractNurlVideoCrid(bids[i].NURL)
684
685 bids[i].CrID = crid
686 bids[i].ImpID = xtrnal.Imp[i].ID
687 - bids[i].H = ptrutil.ValueOrDefault(xtrnal.Imp[i].Video.H)
+ bids[i].H = *xtrnal.Imp[i].Video.H
688 - bids[i].W = ptrutil.ValueOrDefault(xtrnal.Imp[i].Video.W)
+ bids[i].W = *xtrnal.Imp[i].Video.W
689 bids[i].ID = fmt.Sprintf("%sNurlVideo", xtrnal.Imp[i].ID)
690 }
691
adapters/beachfront/beachfront.go
Any thoughts from the adapter's owners?
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.
This code is in MakeBids
so, yes, the default value substitution should already have occurred during MakeRequests
. The Beachfront has more logic than most, so if it's hard to determine if these values are guaranteed to not be nil here, perhaps a little extra protection isn't bad.
Beachfront has reviewed and approved the changes in this PR.
], | ||
"cid": "277", | ||
"crid": "532", | ||
"w": 300, |
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.
Should we assume that the mock response will have a value of 100 instead? Or do we expect the minimum width to be 300?
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 it matters for the test, but I can update it for consistency.
request.Geo = geo | ||
request.Geo = geo{ | ||
Lon: float32(ptrutil.ValueOrDefault(openRTBRequest.Device.Geo.Lon)), | ||
Lat: float32(ptrutil.ValueOrDefault(openRTBRequest.Device.Geo.Lat)), |
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 realize this is beyond the scope of this PR but Geo.Lon
and Geo.Lat
point to float64
values and when casting them to float32
we risk wrapping the values around. Should we add additional logic to cap the values to the math.MaxFloat32
constant before assigning? I'm curious of @ahmetfaruk59 's thoughts on this.
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.
The range for Lat is -90 to 90 and the range for Lon is -180 to 180. Neither approach the maximum size for float32, so the conversion from float64 to float32 may just reduce precision. If a value is so large that it may wrap around, it's invalid data.
assert.Equal(t, recorder.Code, 500, "Should catch error in request") | ||
assert.Equal(t, "Critical error while running the video endpoint: request missing required field: PodConfig.DurationRangeSec request missing required field: PodConfig.Pods", errorMessage, "Incorrect request validation message") | ||
assert.Equal(t, 500, recorder.Code, "Should catch error in request") | ||
assert.Equal(t, errorMessage, "Critical error while running the video endpoint: request missing required field: PodConfig.DurationRangeSec request missing required field: PodConfig.Pods", "Incorrect request validation message") |
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.
The hardcoded string seems to be the expected value. Should we rollback the order of the params in this particular assert.Equal
call?
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.
Good catch. Reverted.
|
||
assert.Equal(t, videoReq.User, bidReq.User, "User is incorrect") | ||
assert.Equal(t, bidReq.User, videoReq.User, "User is incorrect") |
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.
Given that the videoReq
seems to have all the hardcoded values above, should we rollback to put its values as the expected params in these assert.Equal
calls?
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, reverted.
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.
In the github.com/prebid/openrtb/v20/openrtb2
repo, field req.imp[i].ClickBrowser
was recently modified to be a pointer. Are we missing a ptrutil.Clone
call in the ImpWrapper
's Clone()
definition?
1535 func (w *ImpWrapper) Clone() *ImpWrapper {
1536 if w == nil {
1537 return nil
1538 }
1539
1540 clone := *w
1541 clone.impExt = w.impExt.Clone()
+ clone.ClickBrowser = ptrutil.Clone(w.ClickBrowser)
1542
1543 return &clone
1544 }
openrtb_ext/request_wrapper.go
Actually, I see a lot of references in the
Do we need this? If so, does it belong in a separate PR? |
That's ok. Similar to the RequestWrapper, the ImpWrapper is cloning it's own state which only includes the |
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
Updates Prebid Server to use the latest release of the Prebid OpenRTB library.
Change log: https://github.com/prebid/openrtb/releases/tag/v20.1.0
Request Reviews from Affected Adapters: