Skip to content
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

Merged
merged 23 commits into from
Jan 29, 2024
Merged

Update to OpenRTB 2.6-202309 #3387

merged 23 commits into from
Jan 29, 2024

Conversation

SyntaxNode
Copy link
Contributor

@SyntaxNode SyntaxNode commented Jan 5, 2024

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:

adapters/33across/33across.go Show resolved Hide resolved
adapters/beachfront/beachfront.go Outdated Show resolved Hide resolved
@@ -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) {
Copy link
Contributor Author

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?

adapters/eplanning/eplanning.go Show resolved Hide resolved
@@ -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 {
Copy link
Contributor Author

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
}
}
}
Copy link
Contributor Author

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
Copy link
Contributor Author

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.

Copy link
Contributor Author

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
}
Copy link
Contributor Author

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")
})
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced with ptrutil.

@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
videoCopy := *imp.Video
videoCopy.W = ptrutil.ToPtr[int64](defaultVideoWidth)
videoCopy.H = ptrutil.ToPtr[int64](defaultVideoHeight)
imp.Video = &videoCopy
Copy link
Contributor Author

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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.

adapters/huaweiads/huaweiads.go Show resolved Hide resolved
adapters/huaweiads/huaweiads.go Show resolved Hide resolved
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@prebid prebid deleted a comment from github-actions bot Jan 5, 2024
@muncha
Copy link
Contributor

muncha commented Jan 8, 2024

@SyntaxNode
I am no longer the maintainer for Beachfront's adapter, nor associated with them. An email to [email protected] should get to the right people to have a look at this and update their maintainer info. It was a pleasure working on this project. Rock on.

adapters/audienceNetwork/facebook.go Outdated Show resolved Hide resolved
adapters/beachfront/beachfront.go Outdated Show resolved Hide resolved
Comment on lines +315 to +335
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
}
}
}
}
Copy link
Contributor

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
            }
        }
    }
}

Copy link
Contributor Author

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?

Copy link
Contributor

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.

adapters/huaweiads/huaweiads.go Show resolved Hide resolved
adapters/huaweiads/huaweiads.go Show resolved Hide resolved
adapters/huaweiads/huaweiads.go Show resolved Hide resolved
adapters/huaweiads/huaweiads.go Show resolved Hide resolved
@prebid prebid deleted a comment from github-actions bot Jan 17, 2024
@SyntaxNode
Copy link
Contributor Author

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.

Copy link
Contributor

@guscarreon guscarreon left a 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)
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@prebid prebid deleted a comment from github-actions bot Jan 23, 2024
@prebid prebid deleted a comment from github-actions bot Jan 23, 2024
@prebid prebid deleted a comment from github-actions bot Jan 24, 2024
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)
Copy link
Contributor

@guscarreon guscarreon Jan 25, 2024

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?

Copy link
Contributor Author

@SyntaxNode SyntaxNode Jan 25, 2024

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,
Copy link
Contributor

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?

Copy link
Contributor Author

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)),
Copy link
Contributor

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.

Copy link
Contributor Author

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")
Copy link
Contributor

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?

Copy link
Contributor Author

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")
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, reverted.

@prebid prebid deleted a comment from github-actions bot Jan 25, 2024
@prebid prebid deleted a comment from github-actions bot Jan 25, 2024
Copy link
Contributor

@guscarreon guscarreon left a 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

@guscarreon
Copy link
Contributor

Actually, I see a lot of references in the Imp struct, not being cloned by (w *ImpWrapper) Clone() *ImpWrapper method such as:

	Banner *Banner `json:"banner,omitempty"`
	Video *Video `json:"video,omitempty"`
	Audio *Audio `json:"audio,omitempty"`
	Native *Native `json:"native,omitempty"`
	PMP *PMP `json:"pmp,omitempty"`
	Qty *Qty `json:"qty,omitempty"`
	Refresh *Refresh `json:"refresh,omitempty"`

Do we need this? If so, does it belong in a separate PR?

@SyntaxNode
Copy link
Contributor Author

Actually, I see a lot of references in the Imp struct, not being cloned by (w *ImpWrapper) Clone() *ImpWrapper method

That's ok. Similar to the RequestWrapper, the ImpWrapper is cloning it's own state which only includes the ext objects. Just as it's not expected for the RequestWrapper to clone the wrapped request, the ImpWrapper does not clone the wrapped impression.

Copy link
Contributor

@guscarreon guscarreon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bsardo bsardo merged commit dd07431 into prebid:master Jan 29, 2024
7 checks passed
@bsardo bsardo changed the title Update To OpenRTB 2.6-202309 Update to OpenRTB 2.6-202309 Jan 29, 2024
@SyntaxNode SyntaxNode deleted the ortb26-202309 branch January 31, 2024 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants