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

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