github.com/prebid/prebid-server/v2@v2.18.0/adservertargeting/requestlookup.go (about) 1 package adservertargeting 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/url" 7 "strings" 8 9 "github.com/buger/jsonparser" 10 "github.com/pkg/errors" 11 "github.com/prebid/prebid-server/v2/openrtb_ext" 12 ) 13 14 func getAdServerTargeting(reqWrapper *openrtb_ext.RequestWrapper) ([]openrtb_ext.AdServerTarget, error) { 15 reqExt, err := reqWrapper.GetRequestExt() 16 if err != nil { 17 return nil, err 18 } 19 20 reqExtPrebid := reqExt.GetPrebid() 21 if reqExtPrebid == nil { 22 return nil, nil 23 } 24 25 return reqExtPrebid.AdServerTargeting, nil 26 } 27 28 func validateAdServerTargeting(adServerTargeting []openrtb_ext.AdServerTarget) ([]openrtb_ext.AdServerTarget, []openrtb_ext.ExtBidderMessage) { 29 var validatedAdServerTargeting []openrtb_ext.AdServerTarget 30 var warnings []openrtb_ext.ExtBidderMessage 31 for i, targetingObj := range adServerTargeting { 32 33 isDataCorrect := true 34 35 if len(targetingObj.Key) == 0 { 36 isDataCorrect = false 37 warnings = append(warnings, createWarning(fmt.Sprintf("Key is empty for the ad server targeting object at index %d", i))) 38 } 39 40 if len(targetingObj.Value) == 0 { 41 isDataCorrect = false 42 warnings = append(warnings, createWarning(fmt.Sprintf("Value is empty for the ad server targeting object at index %d", i))) 43 } 44 45 targetingObjSource := DataSource(strings.ToLower(targetingObj.Source)) 46 if targetingObjSource != SourceStatic && 47 targetingObjSource != SourceBidRequest && 48 targetingObjSource != SourceBidResponse { 49 isDataCorrect = false 50 warnings = append(warnings, createWarning(fmt.Sprintf("Incorrect source for the ad server targeting object at index %d", i))) 51 } 52 53 if isDataCorrect { 54 validatedAdServerTargeting = append(validatedAdServerTargeting, targetingObj) 55 } 56 57 } 58 return validatedAdServerTargeting, warnings 59 } 60 61 func getValueFromBidRequest(dataHolder *requestCache, path string, queryParams url.Values) (RequestTargetingData, error) { 62 //use the path specified in 'value' to look for data in the ortb bidrequest. 63 res := RequestTargetingData{} 64 65 //check if key points to query param from ext.prebid.amp.data 66 ampDataValue, err := getValueFromQueryParam(path, queryParams) 67 if ampDataValue != nil || err != nil { 68 res.SingleVal = ampDataValue 69 return res, err 70 } 71 72 // check if key points to imp data 73 impData, err := getValueFromImp(path, dataHolder) 74 if len(impData) > 0 || err != nil { 75 res.TargetingValueByImpId = impData 76 return res, err 77 } 78 79 // get data by key from request 80 requestValue, err := getDataFromRequestJson(path, dataHolder) 81 if requestValue != nil || err != nil { 82 res.SingleVal = requestValue 83 return res, err 84 } 85 86 return res, nil 87 } 88 89 func getValueFromQueryParam(path string, queryParams url.Values) (json.RawMessage, error) { 90 ampDataSplit, hasPrefix := verifyPrefixAndTrim(path, "ext.prebid.amp.data.") 91 if hasPrefix { 92 val := queryParams.Get(ampDataSplit) 93 if val != "" { 94 return json.RawMessage(val), nil 95 } else { 96 return nil, errors.Errorf("value not found for path: %s", path) 97 } 98 } 99 return nil, nil 100 } 101 102 func getValueFromImp(path string, dataHolder *requestCache) (map[string][]byte, error) { 103 impsDatas := make(map[string][]byte, 0) 104 impSplit, hasPrefix := verifyPrefixAndTrim(path, "imp.") 105 if hasPrefix { 106 //If imp is specified in the path, the assumption is that the specific imp[] desired corresponds 107 //to the seatbid[].bid[] we're working on. i.e. imp[].id=seatbid[].bid[].impid 108 // key points to data in imp 109 keySplit := strings.Split(impSplit, pathDelimiter) 110 impsData, err := dataHolder.GetImpsData() 111 if err != nil { 112 return nil, err 113 } 114 for _, impData := range impsData { 115 id, _, _, err := jsonparser.Get(impData, "id") 116 if err != nil { 117 return nil, err 118 } 119 value, err := typedLookup(impData, path, keySplit...) 120 if err != nil { 121 return nil, err 122 } 123 impsDatas[string(id)] = value 124 } 125 } 126 return impsDatas, nil 127 } 128 129 func getDataFromRequestJson(path string, dataHolder *requestCache) (json.RawMessage, error) { 130 keySplit := strings.Split(path, pathDelimiter) 131 reqJson := dataHolder.GetReqJson() 132 value, err := typedLookup(reqJson, path, keySplit...) 133 134 if err != nil { 135 return nil, err 136 } 137 return value, nil 138 }