github.com/prebid/prebid-server/v2@v2.18.0/adapters/aax/aax.go (about) 1 package aax 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "net/url" 8 9 "github.com/prebid/openrtb/v20/openrtb2" 10 "github.com/prebid/prebid-server/v2/adapters" 11 "github.com/prebid/prebid-server/v2/config" 12 "github.com/prebid/prebid-server/v2/errortypes" 13 "github.com/prebid/prebid-server/v2/openrtb_ext" 14 ) 15 16 type adapter struct { 17 endpoint string 18 } 19 20 type aaxResponseBidExt struct { 21 AdCodeType string `json:"adCodeType"` 22 } 23 24 func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { 25 var errs []error 26 27 reqJson, err := json.Marshal(request) 28 if err != nil { 29 errs = append(errs, err) 30 return nil, errs 31 } 32 33 headers := http.Header{} 34 headers.Add("Content-Type", "application/json;charset=utf-8") 35 36 return []*adapters.RequestData{{ 37 Method: "POST", 38 Uri: a.endpoint, 39 Body: reqJson, 40 Headers: headers, 41 ImpIDs: openrtb_ext.GetImpIDs(request.Imp), 42 }}, errs 43 } 44 45 func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { 46 var errs []error 47 48 if response.StatusCode == http.StatusNoContent { 49 return nil, nil 50 } 51 52 if response.StatusCode == http.StatusBadRequest { 53 return nil, []error{&errortypes.BadInput{ 54 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 55 }} 56 } 57 58 if response.StatusCode != http.StatusOK { 59 return nil, []error{&errortypes.BadServerResponse{ 60 Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), 61 }} 62 } 63 64 var bidResp openrtb2.BidResponse 65 66 if err := json.Unmarshal(response.Body, &bidResp); err != nil { 67 return nil, []error{err} 68 } 69 70 bidResponse := adapters.NewBidderResponse() 71 72 for _, seatBid := range bidResp.SeatBid { 73 for i := range seatBid.Bid { 74 bidType, err := getMediaTypeForImp(seatBid.Bid[i], internalRequest.Imp) 75 if err != nil { 76 errs = append(errs, err) 77 } else { 78 b := &adapters.TypedBid{ 79 Bid: &seatBid.Bid[i], 80 BidType: bidType, 81 } 82 bidResponse.Bids = append(bidResponse.Bids, b) 83 } 84 } 85 } 86 return bidResponse, errs 87 } 88 89 // Builder builds a new instance of the Aax adapter for the given bidder with the given config. 90 func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { 91 url := buildEndpoint(config.Endpoint, config.ExtraAdapterInfo) 92 return &adapter{ 93 endpoint: url, 94 }, nil 95 } 96 97 func getMediaTypeForImp(bid openrtb2.Bid, imps []openrtb2.Imp) (openrtb_ext.BidType, error) { 98 var bidExt aaxResponseBidExt 99 err := json.Unmarshal(bid.Ext, &bidExt) 100 if err == nil { 101 switch bidExt.AdCodeType { 102 case "banner": 103 return openrtb_ext.BidTypeBanner, nil 104 case "native": 105 return openrtb_ext.BidTypeNative, nil 106 case "video": 107 return openrtb_ext.BidTypeVideo, nil 108 } 109 } 110 111 var mediaType openrtb_ext.BidType 112 var typeCnt = 0 113 for _, imp := range imps { 114 if imp.ID == bid.ImpID { 115 if imp.Banner != nil { 116 typeCnt += 1 117 mediaType = openrtb_ext.BidTypeBanner 118 } 119 if imp.Native != nil { 120 typeCnt += 1 121 mediaType = openrtb_ext.BidTypeNative 122 } 123 if imp.Video != nil { 124 typeCnt += 1 125 mediaType = openrtb_ext.BidTypeVideo 126 } 127 } 128 } 129 if typeCnt == 1 { 130 return mediaType, nil 131 } 132 return mediaType, fmt.Errorf("unable to fetch mediaType in multi-format: %s", bid.ImpID) 133 } 134 135 func buildEndpoint(aaxUrl, hostUrl string) string { 136 137 if len(hostUrl) == 0 { 138 return aaxUrl 139 } 140 urlObject, err := url.Parse(aaxUrl) 141 if err != nil { 142 return aaxUrl 143 } 144 values := urlObject.Query() 145 values.Add("src", hostUrl) 146 urlObject.RawQuery = values.Encode() 147 return urlObject.String() 148 }