github.com/prebid/prebid-server@v0.275.0/adapters/adtrgtme/adtrgtme.go (about)

     1  package adtrgtme
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/prebid/openrtb/v19/openrtb2"
     9  
    10  	"github.com/prebid/prebid-server/adapters"
    11  	"github.com/prebid/prebid-server/config"
    12  	"github.com/prebid/prebid-server/errortypes"
    13  	"github.com/prebid/prebid-server/openrtb_ext"
    14  )
    15  
    16  type adapter struct {
    17  	endpoint string
    18  }
    19  
    20  // Builder builds a new instance of the Adtrgtme adapter for the given bidder with the given config.
    21  func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
    22  	bidder := &adapter{
    23  		endpoint: config.Endpoint,
    24  	}
    25  	return bidder, nil
    26  }
    27  
    28  func (v *adapter) MakeRequests(
    29  	openRTBRequest *openrtb2.BidRequest,
    30  	requestInfo *adapters.ExtraRequestInfo,
    31  ) (
    32  	[]*adapters.RequestData,
    33  	[]error,
    34  ) {
    35  	var requests []*adapters.RequestData
    36  	var errors []error
    37  
    38  	requestCopy := *openRTBRequest
    39  	for _, imp := range openRTBRequest.Imp {
    40  		siteID, err := getSiteIDFromImp(&imp)
    41  		if err != nil {
    42  			errors = append(errors, err)
    43  			continue
    44  		}
    45  
    46  		imp.Ext = nil
    47  		requestCopy.Imp = []openrtb2.Imp{imp}
    48  
    49  		requestBody, err := json.Marshal(requestCopy)
    50  		if err != nil {
    51  			errors = append(errors, err)
    52  			continue
    53  		}
    54  
    55  		requestData := &adapters.RequestData{
    56  			Method:  http.MethodPost,
    57  			Uri:     v.buildRequestURI(siteID),
    58  			Body:    requestBody,
    59  			Headers: makeRequestHeaders(openRTBRequest),
    60  		}
    61  
    62  		requests = append(requests, requestData)
    63  	}
    64  	return requests, errors
    65  }
    66  
    67  func getSiteIDFromImp(imp *openrtb2.Imp) (uint64, error) {
    68  	var bidderExt adapters.ExtImpBidder
    69  	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
    70  		return 0, &errortypes.BadInput{
    71  			Message: "ext.bidder not provided",
    72  		}
    73  	}
    74  	var ext openrtb_ext.ExtImpAdtrgtme
    75  	if err := json.Unmarshal(bidderExt.Bidder, &ext); err != nil {
    76  		return 0, &errortypes.BadInput{
    77  			Message: "ext.bidder not provided",
    78  		}
    79  	}
    80  	return ext.SiteID, nil
    81  }
    82  
    83  func (v *adapter) buildRequestURI(siteID uint64) string {
    84  	return fmt.Sprintf("%s?s=%d&prebid", v.endpoint, siteID)
    85  }
    86  
    87  func makeRequestHeaders(openRTBRequest *openrtb2.BidRequest) http.Header {
    88  	headers := http.Header{}
    89  	headers.Add("Content-Type", "application/json;charset=utf-8")
    90  	headers.Add("Accept", "application/json")
    91  	headers.Add("X-Openrtb-Version", "2.5")
    92  
    93  	if openRTBRequest.Device != nil {
    94  		if len(openRTBRequest.Device.UA) > 0 {
    95  			headers.Add("User-Agent", openRTBRequest.Device.UA)
    96  		}
    97  
    98  		if len(openRTBRequest.Device.IPv6) > 0 {
    99  			headers.Add("X-Forwarded-For", openRTBRequest.Device.IPv6)
   100  		}
   101  
   102  		if len(openRTBRequest.Device.IP) > 0 {
   103  			headers.Add("X-Forwarded-For", openRTBRequest.Device.IP)
   104  		}
   105  	}
   106  	return headers
   107  }
   108  
   109  func (v *adapter) checkResponseStatusCodes(response *adapters.ResponseData) error {
   110  	if response.StatusCode == http.StatusBadRequest {
   111  		return &errortypes.BadInput{
   112  			Message: fmt.Sprintf("Unexpected status code: [ %d ]", response.StatusCode),
   113  		}
   114  	}
   115  
   116  	if response.StatusCode == http.StatusServiceUnavailable {
   117  		return &errortypes.BadInput{
   118  			Message: fmt.Sprintf("Something went wrong, please contact your Account Manager. Status Code: [ %d ] ", response.StatusCode),
   119  		}
   120  	}
   121  
   122  	if response.StatusCode != http.StatusOK {
   123  		return &errortypes.BadInput{
   124  			Message: fmt.Sprintf("Unexpected status code: [ %d ]. Run with request.debug = 1 for more info", response.StatusCode),
   125  		}
   126  	}
   127  
   128  	return nil
   129  }
   130  
   131  func (v *adapter) MakeBids(
   132  	openRTBRequest *openrtb2.BidRequest,
   133  	requestToBidder *adapters.RequestData,
   134  	bidderRawResponse *adapters.ResponseData,
   135  ) (
   136  	*adapters.BidderResponse,
   137  	[]error,
   138  ) {
   139  	if bidderRawResponse.StatusCode == http.StatusNoContent {
   140  		return nil, nil
   141  	}
   142  
   143  	httpStatusError := v.checkResponseStatusCodes(bidderRawResponse)
   144  	if httpStatusError != nil {
   145  		return nil, []error{httpStatusError}
   146  	}
   147  
   148  	var response openrtb2.BidResponse
   149  	if err := json.Unmarshal(bidderRawResponse.Body, &response); err != nil {
   150  		return nil, []error{&errortypes.BadServerResponse{
   151  			Message: "Bad Server Response",
   152  		}}
   153  	}
   154  
   155  	if len(response.SeatBid) == 0 {
   156  		return nil, []error{&errortypes.BadServerResponse{
   157  			Message: "Empty SeatBid array",
   158  		}}
   159  	}
   160  
   161  	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(openRTBRequest.Imp))
   162  	bidResponse.Currency = response.Cur
   163  	for _, seatBid := range response.SeatBid {
   164  		for i, bid := range seatBid.Bid {
   165  			bidType, err := getMediaTypeForImp(bid.ImpID, openRTBRequest.Imp)
   166  			if err != nil {
   167  				return nil, []error{err}
   168  			}
   169  
   170  			b := &adapters.TypedBid{
   171  				Bid:     &seatBid.Bid[i],
   172  				BidType: bidType,
   173  			}
   174  			bidResponse.Bids = append(bidResponse.Bids, b)
   175  		}
   176  	}
   177  	return bidResponse, nil
   178  }
   179  
   180  func getMediaTypeForImp(impId string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) {
   181  	for _, imp := range imps {
   182  		if imp.ID == impId {
   183  			if imp.Banner != nil {
   184  				return openrtb_ext.BidTypeBanner, nil
   185  			} else {
   186  				return "", &errortypes.BadInput{
   187  					Message: fmt.Sprintf("Unsupported bidtype for bid: \"%s\"", impId),
   188  				}
   189  			}
   190  		}
   191  	}
   192  	return "", &errortypes.BadInput{
   193  		Message: fmt.Sprintf("Failed to find impression: \"%s\"", impId),
   194  	}
   195  }