Skip to content

Commit

Permalink
Extract FPD Merge To Separate Package (prebid#3533)
Browse files Browse the repository at this point in the history
  • Loading branch information
SyntaxNode authored Mar 11, 2024
1 parent 0362eb4 commit 40fd4ff
Show file tree
Hide file tree
Showing 10 changed files with 757 additions and 838 deletions.
170 changes: 27 additions & 143 deletions firstpartydata/first_party_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ package firstpartydata

import (
"encoding/json"
"errors"
"fmt"

"github.com/prebid/openrtb/v20/openrtb2"
jsonpatch "gopkg.in/evanphx/json-patch.v4"

"github.com/prebid/prebid-server/v2/errortypes"
"github.com/prebid/prebid-server/v2/openrtb_ext"
"github.com/prebid/prebid-server/v2/ortb"
"github.com/prebid/prebid-server/v2/util/jsonutil"
"github.com/prebid/prebid-server/v2/ortb/merge"
"github.com/prebid/prebid-server/v2/util/ptrutil"
)

var (
ErrBadFPD = errors.New("invalid first party data ext")
)

const (
siteKey = "site"
appKey = "app"
Expand Down Expand Up @@ -195,42 +199,18 @@ func resolveUser(fpdConfig *openrtb_ext.ORTB2, bidRequestUser *openrtb2.User, gl
newUser.Data = openRtbGlobalFPD[userDataKey]
}
if fpdConfigUser != nil {
if err := mergeUser(newUser, fpdConfigUser); err != nil {
var err error
if newUser, err = merge.User(newUser, fpdConfigUser); err != nil {
if err == merge.ErrBadOverride {
return nil, ErrBadFPD
}
return nil, err
}
}

return newUser, nil
}

func mergeUser(v *openrtb2.User, overrideJSON json.RawMessage) error {
*v = *ortb.CloneUser(v)

// Track EXTs
// It's not necessary to track `ext` fields in array items because the array
// items will be replaced entirely with the override JSON, so no merge is required.
var ext, extGeo extMerger
ext.Track(&v.Ext)
if v.Geo != nil {
extGeo.Track(&v.Geo.Ext)
}

// Merge
if err := jsonutil.Unmarshal(overrideJSON, &v); err != nil {
return err
}

// Merge EXTs
if err := ext.Merge(); err != nil {
return err
}
if err := extGeo.Merge(); err != nil {
return err
}

return nil
}

func resolveSite(fpdConfig *openrtb_ext.ORTB2, bidRequestSite *openrtb2.Site, globalFPD map[string][]byte, openRtbGlobalFPD map[string][]openrtb2.Data, bidderName string) (*openrtb2.Site, error) {
var fpdConfigSite json.RawMessage

Expand Down Expand Up @@ -278,70 +258,22 @@ func resolveSite(fpdConfig *openrtb_ext.ORTB2, bidRequestSite *openrtb2.Site, gl
newSite.Content.Data = openRtbGlobalFPD[siteContentDataKey]
}
if fpdConfigSite != nil {
if err := mergeSite(newSite, fpdConfigSite, bidderName); err != nil {
var err error
if newSite, err = merge.Site(newSite, fpdConfigSite, bidderName); err != nil {
if err == merge.ErrBadOverride {
return nil, ErrBadFPD
}
return nil, err
}
}
return newSite, nil
}

func mergeSite(v *openrtb2.Site, overrideJSON json.RawMessage, bidderName string) error {
*v = *ortb.CloneSite(v)

// Track EXTs
// It's not necessary to track `ext` fields in array items because the array
// items will be replaced entirely with the override JSON, so no merge is required.
var ext, extPublisher, extContent, extContentProducer, extContentNetwork, extContentChannel extMerger
ext.Track(&v.Ext)
if v.Publisher != nil {
extPublisher.Track(&v.Publisher.Ext)
}
if v.Content != nil {
extContent.Track(&v.Content.Ext)
}
if v.Content != nil && v.Content.Producer != nil {
extContentProducer.Track(&v.Content.Producer.Ext)
}
if v.Content != nil && v.Content.Network != nil {
extContentNetwork.Track(&v.Content.Network.Ext)
}
if v.Content != nil && v.Content.Channel != nil {
extContentChannel.Track(&v.Content.Channel.Ext)
}

// Merge
if err := jsonutil.Unmarshal(overrideJSON, &v); err != nil {
return err
}

// Merge EXTs
if err := ext.Merge(); err != nil {
return err
}
if err := extPublisher.Merge(); err != nil {
return err
}
if err := extContent.Merge(); err != nil {
return err
}
if err := extContentProducer.Merge(); err != nil {
return err
}
if err := extContentNetwork.Merge(); err != nil {
return err
}
if err := extContentChannel.Merge(); err != nil {
return err
}

// Re-Validate Site
if v.ID == "" && v.Page == "" {
return &errortypes.BadInput{
Message: fmt.Sprintf("incorrect First Party Data for bidder %s: Site object cannot set empty page if req.site.id is empty", bidderName),
// Re-Validate Site
if newSite.ID == "" && newSite.Page == "" {
return nil, &errortypes.BadInput{
Message: fmt.Sprintf("incorrect First Party Data for bidder %s: Site object cannot set empty page if req.site.id is empty", bidderName),
}
}
}

return nil
return newSite, nil
}

func resolveApp(fpdConfig *openrtb_ext.ORTB2, bidRequestApp *openrtb2.App, globalFPD map[string][]byte, openRtbGlobalFPD map[string][]openrtb2.Data, bidderName string) (*openrtb2.App, error) {
Expand Down Expand Up @@ -394,66 +326,18 @@ func resolveApp(fpdConfig *openrtb_ext.ORTB2, bidRequestApp *openrtb2.App, globa
}

if fpdConfigApp != nil {
if err := mergeApp(newApp, fpdConfigApp); err != nil {
var err error
if newApp, err = merge.App(newApp, fpdConfigApp); err != nil {
if err == merge.ErrBadOverride {
return nil, ErrBadFPD
}
return nil, err
}
}

return newApp, nil
}

func mergeApp(v *openrtb2.App, overrideJSON json.RawMessage) error {
*v = *ortb.CloneApp(v)

// Track EXTs
// It's not necessary to track `ext` fields in array items because the array
// items will be replaced entirely with the override JSON, so no merge is required.
var ext, extPublisher, extContent, extContentProducer, extContentNetwork, extContentChannel extMerger
ext.Track(&v.Ext)
if v.Publisher != nil {
extPublisher.Track(&v.Publisher.Ext)
}
if v.Content != nil {
extContent.Track(&v.Content.Ext)
}
if v.Content != nil && v.Content.Producer != nil {
extContentProducer.Track(&v.Content.Producer.Ext)
}
if v.Content != nil && v.Content.Network != nil {
extContentNetwork.Track(&v.Content.Network.Ext)
}
if v.Content != nil && v.Content.Channel != nil {
extContentChannel.Track(&v.Content.Channel.Ext)
}

// Merge
if err := jsonutil.Unmarshal(overrideJSON, &v); err != nil {
return err
}

// Merge EXTs
if err := ext.Merge(); err != nil {
return err
}
if err := extPublisher.Merge(); err != nil {
return err
}
if err := extContent.Merge(); err != nil {
return err
}
if err := extContentProducer.Merge(); err != nil {
return err
}
if err := extContentNetwork.Merge(); err != nil {
return err
}
if err := extContentChannel.Merge(); err != nil {
return err
}

return nil
}

func buildExtData(data []byte) []byte {
res := make([]byte, 0, len(data)+len(`"{"data":}"`))
res = append(res, []byte(`{"data":`)...)
Expand Down
Loading

0 comments on commit 40fd4ff

Please sign in to comment.