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

     1  package adman
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/prebid/openrtb/v19/openrtb2"
     9  	"github.com/prebid/prebid-server/adapters"
    10  	"github.com/prebid/prebid-server/config"
    11  	"github.com/prebid/prebid-server/errortypes"
    12  	"github.com/prebid/prebid-server/openrtb_ext"
    13  )
    14  
    15  // AdmanAdapter struct
    16  type AdmanAdapter struct {
    17  	URI string
    18  }
    19  
    20  // Builder builds a new instance of the Adman 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 := &AdmanAdapter{
    23  		URI: config.Endpoint,
    24  	}
    25  	return bidder, nil
    26  }
    27  
    28  // MakeRequests create bid request for adman demand
    29  func (a *AdmanAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
    30  	var errs []error
    31  	var admanExt openrtb_ext.ExtImpAdman
    32  	var err error
    33  
    34  	var adapterRequests []*adapters.RequestData
    35  
    36  	reqCopy := *request
    37  	for _, imp := range request.Imp {
    38  		reqCopy.Imp = []openrtb2.Imp{imp}
    39  
    40  		var bidderExt adapters.ExtImpBidder
    41  		if err = json.Unmarshal(reqCopy.Imp[0].Ext, &bidderExt); err != nil {
    42  			errs = append(errs, err)
    43  			continue
    44  		}
    45  
    46  		if err = json.Unmarshal(bidderExt.Bidder, &admanExt); err != nil {
    47  			errs = append(errs, err)
    48  			continue
    49  		}
    50  
    51  		reqCopy.Imp[0].TagID = admanExt.TagID
    52  
    53  		adapterReq, errors := a.makeRequest(&reqCopy)
    54  		if adapterReq != nil {
    55  			adapterRequests = append(adapterRequests, adapterReq)
    56  		}
    57  		errs = append(errs, errors...)
    58  	}
    59  	return adapterRequests, errs
    60  }
    61  
    62  func (a *AdmanAdapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, []error) {
    63  
    64  	var errs []error
    65  
    66  	reqJSON, err := json.Marshal(request)
    67  
    68  	if err != nil {
    69  		errs = append(errs, err)
    70  		return nil, errs
    71  	}
    72  
    73  	headers := http.Header{}
    74  	headers.Add("Content-Type", "application/json;charset=utf-8")
    75  	headers.Add("Accept", "application/json")
    76  	return &adapters.RequestData{
    77  		Method:  "POST",
    78  		Uri:     a.URI,
    79  		Body:    reqJSON,
    80  		Headers: headers,
    81  	}, errs
    82  }
    83  
    84  // MakeBids makes the bids
    85  func (a *AdmanAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
    86  	var errs []error
    87  
    88  	if response.StatusCode == http.StatusNoContent {
    89  		return nil, nil
    90  	}
    91  
    92  	if response.StatusCode == http.StatusNotFound {
    93  		return nil, []error{&errortypes.BadServerResponse{
    94  			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode),
    95  		}}
    96  	}
    97  
    98  	var bidResp openrtb2.BidResponse
    99  
   100  	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
   101  		return nil, []error{err}
   102  	}
   103  
   104  	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
   105  
   106  	for _, sb := range bidResp.SeatBid {
   107  		for i := range sb.Bid {
   108  			bidType, err := getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp)
   109  			if err != nil {
   110  				errs = append(errs, err)
   111  			} else {
   112  				b := &adapters.TypedBid{
   113  					Bid:     &sb.Bid[i],
   114  					BidType: bidType,
   115  				}
   116  				bidResponse.Bids = append(bidResponse.Bids, b)
   117  			}
   118  		}
   119  	}
   120  	return bidResponse, errs
   121  }
   122  
   123  func getMediaTypeForImp(impID string, imps []openrtb2.Imp) (openrtb_ext.BidType, error) {
   124  	mediaType := openrtb_ext.BidTypeBanner
   125  	for _, imp := range imps {
   126  		if imp.ID == impID {
   127  			if imp.Banner == nil && imp.Video != nil {
   128  				mediaType = openrtb_ext.BidTypeVideo
   129  			}
   130  			return mediaType, nil
   131  		}
   132  	}
   133  
   134  	// This shouldnt happen. Lets handle it just incase by returning an error.
   135  	return "", &errortypes.BadInput{
   136  		Message: fmt.Sprintf("Failed to find impression \"%s\" ", impID),
   137  	}
   138  }