github.com/prebid/prebid-server/v2@v2.18.0/adapters/adyoulike/adyoulike.go (about)

     1  package adyoulike
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"strings"
     8  
     9  	"github.com/buger/jsonparser"
    10  	"github.com/prebid/openrtb/v20/openrtb2"
    11  	"github.com/prebid/prebid-server/v2/adapters"
    12  	"github.com/prebid/prebid-server/v2/config"
    13  	"github.com/prebid/prebid-server/v2/errortypes"
    14  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    15  )
    16  
    17  func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
    18  	return &adapter{
    19  		endpoint: config.Endpoint,
    20  	}, nil
    21  }
    22  
    23  type adapter struct {
    24  	endpoint string
    25  }
    26  
    27  func (a *adapter) MakeRequests(
    28  	openRTBRequest *openrtb2.BidRequest,
    29  	reqInfo *adapters.ExtraRequestInfo,
    30  ) (
    31  	requestsToBidder []*adapters.RequestData,
    32  	errs []error,
    33  ) {
    34  	var err error
    35  	var tagID string
    36  
    37  	reqCopy := *openRTBRequest
    38  	reqCopy.Imp = []openrtb2.Imp{}
    39  	for ind, imp := range openRTBRequest.Imp {
    40  
    41  		// Check if imp comes with bid floor amount defined in a foreign currency
    42  		if imp.BidFloor > 0 && imp.BidFloorCur != "" && strings.ToUpper(imp.BidFloorCur) != "USD" {
    43  			// Convert to US dollars
    44  			convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "USD")
    45  			if err != nil {
    46  				return nil, []error{err}
    47  			}
    48  			// Update after conversion. All imp elements inside request.Imp are shallow copies
    49  			// therefore, their non-pointer values are not shared memory and are safe to modify.
    50  			imp.BidFloorCur = "USD"
    51  			imp.BidFloor = convertedValue
    52  		}
    53  
    54  		// Set the CUR of bid to USD after converting all floors
    55  		reqCopy.Cur = []string{"USD"}
    56  
    57  		reqCopy.Imp = append(reqCopy.Imp, imp)
    58  
    59  		tagID, err = jsonparser.GetString(reqCopy.Imp[ind].Ext, "bidder", "placement")
    60  		if err != nil {
    61  			errs = append(errs, err)
    62  			continue
    63  		}
    64  
    65  		reqCopy.Imp[ind].TagID = tagID
    66  	}
    67  
    68  	openRTBRequestJSON, err := json.Marshal(reqCopy)
    69  	if err != nil {
    70  		errs = append(errs, err)
    71  	}
    72  
    73  	if len(errs) > 0 {
    74  		return nil, errs
    75  	}
    76  
    77  	headers := http.Header{}
    78  	headers.Add("Content-Type", "application/json;charset=utf-8")
    79  	headers.Add("Accept", "application/json")
    80  	headers.Add("x-openrtb-version", "2.5")
    81  
    82  	requestToBidder := &adapters.RequestData{
    83  		Method:  "POST",
    84  		Uri:     a.endpoint,
    85  		Body:    openRTBRequestJSON,
    86  		Headers: headers,
    87  		ImpIDs:  openrtb_ext.GetImpIDs(reqCopy.Imp),
    88  	}
    89  	requestsToBidder = append(requestsToBidder, requestToBidder)
    90  
    91  	return requestsToBidder, errs
    92  }
    93  
    94  const unexpectedStatusCodeFormat = "" +
    95  	"Unexpected status code: %d. Run with request.debug = 1 for more info"
    96  
    97  func (a *adapter) MakeBids(
    98  	openRTBRequest *openrtb2.BidRequest,
    99  	requestToBidder *adapters.RequestData,
   100  	bidderRawResponse *adapters.ResponseData,
   101  ) (
   102  	bidderResponse *adapters.BidderResponse,
   103  	errs []error,
   104  ) {
   105  	switch bidderRawResponse.StatusCode {
   106  	case http.StatusOK:
   107  		break
   108  	case http.StatusNoContent:
   109  		return nil, nil
   110  	case http.StatusBadRequest:
   111  		err := &errortypes.BadInput{
   112  			Message: fmt.Sprintf(unexpectedStatusCodeFormat, bidderRawResponse.StatusCode),
   113  		}
   114  		return nil, []error{err}
   115  	default:
   116  		err := &errortypes.BadServerResponse{
   117  			Message: fmt.Sprintf(unexpectedStatusCodeFormat, bidderRawResponse.StatusCode),
   118  		}
   119  		return nil, []error{err}
   120  	}
   121  
   122  	var openRTBBidderResponse openrtb2.BidResponse
   123  	if err := json.Unmarshal(bidderRawResponse.Body, &openRTBBidderResponse); err != nil {
   124  		return nil, []error{err}
   125  	}
   126  
   127  	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(openRTBRequest.Imp))
   128  	bidResponse.Currency = "USD"
   129  
   130  	for _, seatBid := range openRTBBidderResponse.SeatBid {
   131  		for idx := range seatBid.Bid {
   132  			b := &adapters.TypedBid{
   133  				Bid:     &seatBid.Bid[idx],
   134  				BidType: getMediaTypeForImp(seatBid.Bid[idx].ImpID, openRTBRequest.Imp),
   135  			}
   136  			bidResponse.Bids = append(bidResponse.Bids, b)
   137  		}
   138  	}
   139  	return bidResponse, nil
   140  }
   141  
   142  // getMediaTypeForBid determines which type of bid.
   143  func getMediaTypeForImp(impID string, imps []openrtb2.Imp) openrtb_ext.BidType {
   144  	mediaType := openrtb_ext.BidTypeBanner
   145  	for _, imp := range imps {
   146  		if imp.ID == impID {
   147  			if imp.Banner == nil && imp.Video != nil {
   148  				mediaType = openrtb_ext.BidTypeVideo
   149  			} else if imp.Banner == nil && imp.Native != nil {
   150  				mediaType = openrtb_ext.BidTypeNative
   151  			}
   152  		}
   153  	}
   154  
   155  	return mediaType
   156  }