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

     1  package vidoomy
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/prebid/openrtb/v20/openrtb2"
     9  
    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  	"github.com/prebid/prebid-server/v2/util/ptrutil"
    15  )
    16  
    17  type adapter struct {
    18  	endpoint string
    19  }
    20  
    21  func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
    22  	var errors []error
    23  
    24  	reqs := make([]*adapters.RequestData, 0, len(request.Imp))
    25  
    26  	header := getHeaders(request)
    27  	for _, imp := range request.Imp {
    28  
    29  		// Split up multi-impression requests into multiple requests so that
    30  		// each split request is only associated to a single impression
    31  		reqCopy := *request
    32  		reqCopy.Imp = []openrtb2.Imp{imp}
    33  
    34  		if err := changeRequestForBidService(&reqCopy); err != nil {
    35  			errors = append(errors, err)
    36  			continue
    37  		}
    38  
    39  		reqJSON, err := json.Marshal(&reqCopy)
    40  		if err != nil {
    41  			errors = append(errors, err)
    42  			continue
    43  		}
    44  
    45  		reqs = append(reqs, &adapters.RequestData{
    46  			Method:  "POST",
    47  			Uri:     a.endpoint,
    48  			Body:    reqJSON,
    49  			Headers: header,
    50  			ImpIDs:  openrtb_ext.GetImpIDs(reqCopy.Imp),
    51  		})
    52  	}
    53  
    54  	return reqs, errors
    55  }
    56  
    57  func getHeaders(request *openrtb2.BidRequest) http.Header {
    58  	headers := http.Header{}
    59  
    60  	headers.Add("Content-Type", "application/json;charset=utf-8")
    61  	headers.Add("Accept", "application/json")
    62  	headers.Add("x-openrtb-version", "2.5")
    63  
    64  	if request.Device == nil {
    65  		return headers
    66  	}
    67  
    68  	if request.Device.UA != "" {
    69  		headers.Set("User-Agent", request.Device.UA)
    70  	}
    71  
    72  	if len(request.Device.IPv6) > 0 {
    73  		headers.Add("X-Forwarded-For", request.Device.IPv6)
    74  	}
    75  
    76  	if len(request.Device.IP) > 0 {
    77  		headers.Add("X-Forwarded-For", request.Device.IP)
    78  	}
    79  
    80  	return headers
    81  }
    82  
    83  func changeRequestForBidService(request *openrtb2.BidRequest) error {
    84  	if request.Imp[0].Banner == nil {
    85  		return nil
    86  	}
    87  
    88  	banner := *request.Imp[0].Banner
    89  	request.Imp[0].Banner = &banner
    90  
    91  	if banner.W != nil && banner.H != nil {
    92  		if *banner.W == 0 || *banner.H == 0 {
    93  			return fmt.Errorf("invalid sizes provided for Banner %d x %d", *banner.W, *banner.H)
    94  		}
    95  		return nil
    96  	}
    97  
    98  	if len(banner.Format) == 0 {
    99  		return fmt.Errorf("no sizes provided for Banner %v", banner.Format)
   100  	}
   101  
   102  	banner.W = ptrutil.ToPtr(banner.Format[0].W)
   103  	banner.H = ptrutil.ToPtr(banner.Format[0].H)
   104  
   105  	return nil
   106  }
   107  
   108  func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
   109  	if response.StatusCode == http.StatusNoContent {
   110  		return nil, nil
   111  	}
   112  
   113  	if response.StatusCode != http.StatusOK {
   114  		return nil, []error{&errortypes.BadServerResponse{
   115  			Message: fmt.Sprintf("Unexpected status code: %d.", response.StatusCode),
   116  		}}
   117  	}
   118  
   119  	var bidResp openrtb2.BidResponse
   120  	if err := json.Unmarshal(response.Body, &bidResp); err != nil {
   121  		return nil, []error{&errortypes.BadServerResponse{
   122  			Message: fmt.Sprintf("Bad server response: %d.", err),
   123  		}}
   124  	}
   125  
   126  	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(internalRequest.Imp))
   127  
   128  	for _, sb := range bidResp.SeatBid {
   129  		for _, bid := range sb.Bid {
   130  			bid := bid
   131  			exists, mediaType := getImpInfo(bid.ImpID, internalRequest.Imp)
   132  			if !exists {
   133  				return nil, []error{&errortypes.BadServerResponse{
   134  					Message: fmt.Sprintf("Unknown ad unit code '%s'", bid.ImpID),
   135  				}}
   136  			}
   137  
   138  			if openrtb_ext.BidTypeBanner != mediaType &&
   139  				openrtb_ext.BidTypeVideo != mediaType {
   140  				//only banner and video are supported, anything else is ignored
   141  				continue
   142  			}
   143  
   144  			bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{
   145  				Bid:     &bid,
   146  				BidType: mediaType,
   147  			})
   148  		}
   149  	}
   150  
   151  	return bidResponse, nil
   152  }
   153  
   154  func getImpInfo(impId string, imps []openrtb2.Imp) (bool, openrtb_ext.BidType) {
   155  	var mediaType openrtb_ext.BidType
   156  	for _, imp := range imps {
   157  		if imp.ID == impId {
   158  
   159  			if imp.Video != nil {
   160  				mediaType = openrtb_ext.BidTypeVideo
   161  			} else if imp.Banner != nil {
   162  				mediaType = openrtb_ext.BidTypeBanner
   163  			}
   164  
   165  			return true, mediaType
   166  		}
   167  	}
   168  	return false, mediaType
   169  }
   170  
   171  // Builder builds a new instance of the Vidoomy adapter for the given bidder with the given config.
   172  func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
   173  	bidder := &adapter{
   174  		endpoint: config.Endpoint,
   175  	}
   176  	return bidder, nil
   177  }