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