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

     1  package bluesea
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"net/url"
     8  
     9  	"github.com/prebid/openrtb/v19/openrtb2"
    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  type blueseaBidExt struct {
    21  	MediaType string `json:"mediatype"`
    22  }
    23  
    24  func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
    25  
    26  	bidder := &adapter{
    27  		endpoint: config.Endpoint,
    28  	}
    29  	return bidder, nil
    30  }
    31  
    32  func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
    33  	impCount := len(request.Imp)
    34  
    35  	if impCount == 0 {
    36  		err := &errortypes.BadInput{
    37  			Message: "Empty Imp objects",
    38  		}
    39  		return nil, []error{err}
    40  	}
    41  
    42  	requestDatas := make([]*adapters.RequestData, 0, impCount)
    43  	errs := make([]error, 0, impCount)
    44  
    45  	headers := http.Header{}
    46  	headers.Add("Content-Type", "application/json;charset=utf-8")
    47  	headers.Add("Accept", "application/json")
    48  
    49  	for _, imp := range request.Imp {
    50  		blueseaImpExt, err := extraImpExt(&imp)
    51  		if err != nil {
    52  			errs = append(errs, err)
    53  			continue
    54  		}
    55  		reqJson, err := json.Marshal(request)
    56  		if err != nil {
    57  			errs = append(errs, err)
    58  			continue
    59  		}
    60  
    61  		queryParams := url.Values{}
    62  		queryParams.Add("pubid", blueseaImpExt.PubId)
    63  		queryParams.Add("token", blueseaImpExt.Token)
    64  		queryString := queryParams.Encode()
    65  		requestData := &adapters.RequestData{
    66  			Method:  "POST",
    67  			Uri:     fmt.Sprintf("%s?%s", a.endpoint, queryString),
    68  			Body:    reqJson,
    69  			Headers: headers,
    70  		}
    71  		requestDatas = append(requestDatas, requestData)
    72  	}
    73  	// to safe double check in case the requestDatas is empty and no error is raised.
    74  	if len(requestDatas) == 0 && len(errs) == 0 {
    75  		errs = append(errs, fmt.Errorf("Empty RequestData"))
    76  	}
    77  	return requestDatas, errs
    78  }
    79  
    80  func extraImpExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpBluesea, error) {
    81  	var impExt adapters.ExtImpBidder
    82  	var blueseaImpExt openrtb_ext.ExtImpBluesea
    83  
    84  	err := json.Unmarshal(imp.Ext, &impExt)
    85  	if err != nil {
    86  		return nil, &errortypes.BadInput{
    87  			Message: fmt.Sprintf("Error in parsing imp.ext. err = %v, imp.ext = %v", err.Error(), string(imp.Ext)),
    88  		}
    89  	}
    90  
    91  	err = json.Unmarshal(impExt.Bidder, &blueseaImpExt)
    92  	if err != nil {
    93  		return nil, &errortypes.BadInput{
    94  			Message: fmt.Sprintf("Error in parsing imp.ext.bidder. err = %v, bidder = %v", err.Error(), string(impExt.Bidder)),
    95  		}
    96  	}
    97  	if len(blueseaImpExt.PubId) == 0 || len(blueseaImpExt.Token) == 0 {
    98  		return nil, &errortypes.BadInput{
    99  			Message: fmt.Sprintf("Error in parsing imp.ext.bidder, empty pubid or token"),
   100  		}
   101  	}
   102  	return &blueseaImpExt, nil
   103  }
   104  
   105  func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) {
   106  
   107  	if adapters.IsResponseStatusCodeNoContent(response) {
   108  		return nil, nil
   109  	}
   110  
   111  	if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil {
   112  		return nil, []error{err}
   113  	}
   114  
   115  	var blueseaResponse openrtb2.BidResponse
   116  	if err := json.Unmarshal(response.Body, &blueseaResponse); err != nil {
   117  		return nil, []error{fmt.Errorf("Error in parsing bidresponse body")}
   118  	}
   119  
   120  	var errs []error
   121  	bidResponse := adapters.NewBidderResponseWithBidsCapacity(1)
   122  
   123  	if blueseaResponse.Cur != "" {
   124  		bidResponse.Currency = blueseaResponse.Cur
   125  	}
   126  	for _, seatBid := range blueseaResponse.SeatBid {
   127  		for i, bid := range seatBid.Bid {
   128  			bidType, err := getMediaTypeForBid(&bid)
   129  
   130  			if err != nil {
   131  				errs = append(errs, err)
   132  				continue
   133  			}
   134  			b := &adapters.TypedBid{
   135  				Bid:     &seatBid.Bid[i],
   136  				BidType: bidType,
   137  			}
   138  			bidResponse.Bids = append(bidResponse.Bids, b)
   139  		}
   140  	}
   141  	return bidResponse, errs
   142  }
   143  
   144  func getMediaTypeForBid(bid *openrtb2.Bid) (openrtb_ext.BidType, error) {
   145  
   146  	var bidExt blueseaBidExt
   147  	if err := json.Unmarshal(bid.Ext, &bidExt); err != nil {
   148  		return "", fmt.Errorf("Error in parsing bid.ext")
   149  	}
   150  
   151  	switch bidExt.MediaType {
   152  	case "banner":
   153  		return openrtb_ext.BidTypeBanner, nil
   154  	case "native":
   155  		return openrtb_ext.BidTypeNative, nil
   156  	case "video":
   157  		return openrtb_ext.BidTypeVideo, nil
   158  	default:
   159  		return "", fmt.Errorf("Unknown bid type, %v", bidExt.MediaType)
   160  	}
   161  }