github.com/prebid/prebid-server/v2@v2.18.0/openrtb_ext/multibid.go (about)

     1  package openrtb_ext
     2  
     3  import "fmt"
     4  
     5  const DefaultBidLimit = 1
     6  const MaxBidLimit = 9
     7  
     8  func ValidateAndBuildExtMultiBid(prebid *ExtRequestPrebid) ([]*ExtMultiBid, []error) {
     9  	if prebid == nil || prebid.MultiBid == nil {
    10  		return nil, nil
    11  	}
    12  
    13  	var validationErrs, errs []error
    14  	var validatedMultiBids, newMultiBids []*ExtMultiBid //returning slice instead of map to keep the downstream req.Ext payload consistent
    15  	multiBidMap := make(map[string]struct{})            // map is needed temporarily for validate of duplicate entries, etc.
    16  	for _, multiBid := range prebid.MultiBid {
    17  		newMultiBids, errs = addMultiBid(multiBidMap, multiBid)
    18  		if len(errs) != 0 {
    19  			validationErrs = append(validationErrs, errs...)
    20  		}
    21  		if len(newMultiBids) != 0 {
    22  			validatedMultiBids = append(validatedMultiBids, newMultiBids...)
    23  		}
    24  	}
    25  
    26  	return validatedMultiBids, validationErrs
    27  }
    28  
    29  // Validate and add multiBid
    30  func addMultiBid(multiBidMap map[string]struct{}, multiBid *ExtMultiBid) ([]*ExtMultiBid, []error) {
    31  	errs := make([]error, 0)
    32  
    33  	if multiBid.MaxBids == nil {
    34  		errs = append(errs, fmt.Errorf("maxBids not defined for %v", *multiBid))
    35  		return nil, errs
    36  	}
    37  
    38  	if *multiBid.MaxBids < DefaultBidLimit {
    39  		errs = append(errs, fmt.Errorf("invalid maxBids value, using minimum %d limit for %v", DefaultBidLimit, *multiBid))
    40  		*multiBid.MaxBids = DefaultBidLimit
    41  	}
    42  
    43  	if *multiBid.MaxBids > MaxBidLimit {
    44  		errs = append(errs, fmt.Errorf("invalid maxBids value, using maximum %d limit for %v", MaxBidLimit, *multiBid))
    45  		*multiBid.MaxBids = MaxBidLimit
    46  	}
    47  
    48  	var validatedMultiBids []*ExtMultiBid
    49  	if multiBid.Bidder != "" {
    50  		if _, ok := multiBidMap[multiBid.Bidder]; ok {
    51  			errs = append(errs, fmt.Errorf("multiBid already defined for %s, ignoring this instance %v", multiBid.Bidder, *multiBid))
    52  			return nil, errs
    53  		}
    54  
    55  		if multiBid.Bidders != nil {
    56  			errs = append(errs, fmt.Errorf("ignoring bidders from %v", *multiBid))
    57  			multiBid.Bidders = nil
    58  		}
    59  		multiBidMap[multiBid.Bidder] = struct{}{}
    60  		validatedMultiBids = append(validatedMultiBids, multiBid)
    61  	} else if len(multiBid.Bidders) > 0 {
    62  		var bidders []string
    63  		for _, bidder := range multiBid.Bidders {
    64  			if _, ok := multiBidMap[bidder]; ok {
    65  				errs = append(errs, fmt.Errorf("multiBid already defined for %s, ignoring this instance %v", bidder, *multiBid))
    66  				continue
    67  			}
    68  			multiBidMap[bidder] = struct{}{}
    69  			bidders = append(bidders, bidder)
    70  		}
    71  		if multiBid.TargetBidderCodePrefix != "" {
    72  			errs = append(errs, fmt.Errorf("ignoring targetbiddercodeprefix for %v", *multiBid))
    73  			multiBid.TargetBidderCodePrefix = ""
    74  		}
    75  		if len(bidders) != 0 {
    76  			validatedMultiBids = append(validatedMultiBids, &ExtMultiBid{
    77  				MaxBids: multiBid.MaxBids,
    78  				Bidders: bidders,
    79  			})
    80  		}
    81  	} else {
    82  		errs = append(errs, fmt.Errorf("bidder(s) not specified for %v", *multiBid))
    83  	}
    84  	return validatedMultiBids, errs
    85  }