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

     1  package silvermob
     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 SilverMobAdapter struct {
    18  	endpoint *template.Template
    19  }
    20  
    21  // Builder builds a new instance of the SilverMob 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 := &SilverMobAdapter{
    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 *SilverMobAdapter) MakeRequests(
    58  	openRTBRequest *openrtb2.BidRequest,
    59  	reqInfo *adapters.ExtraRequestInfo,
    60  ) (
    61  	[]*adapters.RequestData,
    62  	[]error,
    63  ) {
    64  	requestCopy := *openRTBRequest
    65  	impCount := len(openRTBRequest.Imp)
    66  	requestData := make([]*adapters.RequestData, 0, impCount)
    67  	errs := []error{}
    68  
    69  	var err error
    70  
    71  	for _, imp := range openRTBRequest.Imp {
    72  		var silvermobExt *openrtb_ext.ExtSilverMob
    73  
    74  		silvermobExt, err = a.getImpressionExt(&imp)
    75  
    76  		if err != nil {
    77  			errs = append(errs, err)
    78  			continue
    79  		}
    80  
    81  		url, err := a.buildEndpointURL(silvermobExt)
    82  		if err != nil {
    83  			errs = append(errs, err)
    84  			continue
    85  		}
    86  
    87  		requestCopy.Imp = []openrtb2.Imp{imp}
    88  		reqJSON, err := json.Marshal(requestCopy)
    89  		if err != nil {
    90  			errs = append(errs, err)
    91  			continue
    92  		}
    93  
    94  		reqData := &adapters.RequestData{
    95  			Method:  http.MethodPost,
    96  			Body:    reqJSON,
    97  			Uri:     url,
    98  			Headers: *GetHeaders(&requestCopy),
    99  		}
   100  
   101  		requestData = append(requestData, reqData)
   102  	}
   103  
   104  	return requestData, errs
   105  }
   106  
   107  func (a *SilverMobAdapter) getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtSilverMob, error) {
   108  	var bidderExt adapters.ExtImpBidder
   109  	if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil {
   110  		return nil, &errortypes.BadInput{
   111  			Message: fmt.Sprintf("error unmarshaling imp.ext: %s", err.Error()),
   112  		}
   113  	}
   114  	var silvermobExt openrtb_ext.ExtSilverMob
   115  	if err := json.Unmarshal(bidderExt.Bidder, &silvermobExt); err != nil {
   116  		return nil, &errortypes.BadInput{
   117  			Message: fmt.Sprintf("error unmarshaling imp.ext.bidder: %s", err.Error()),
   118  		}
   119  	}
   120  	return &silvermobExt, nil
   121  }
   122  
   123  func (a *SilverMobAdapter) buildEndpointURL(params *openrtb_ext.ExtSilverMob) (string, error) {
   124  	endpointParams := macros.EndpointTemplateParams{ZoneID: params.ZoneID, Host: params.Host}
   125  	return macros.ResolveMacros(a.endpoint, endpointParams)
   126  }
   127  
   128  func (a *SilverMobAdapter) MakeBids(
   129  	openRTBRequest *openrtb2.BidRequest,
   130  	requestToBidder *adapters.RequestData,
   131  	bidderRawResponse *adapters.ResponseData,
   132  ) (
   133  	bidderResponse *adapters.BidderResponse,
   134  	errs []error,
   135  ) {
   136  
   137  	if bidderRawResponse.StatusCode == http.StatusNoContent {
   138  		return nil, nil
   139  	}
   140  
   141  	if bidderRawResponse.StatusCode == http.StatusBadRequest {
   142  		return nil, []error{&errortypes.BadInput{
   143  			Message: fmt.Sprintf("Bad Request status code: %d. Run with request.debug = 1 for more info", bidderRawResponse.StatusCode),
   144  		}}
   145  	}
   146  
   147  	if bidderRawResponse.StatusCode != http.StatusOK {
   148  		return nil, []error{fmt.Errorf("Unexpected status code: %d. Run with request.debug = 1 for more info", bidderRawResponse.StatusCode)}
   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: fmt.Sprintf("Error unmarshaling server Response: %s", err),
   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(1)
   166  
   167  	for _, sb := range bidResp.SeatBid {
   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  	}
   175  
   176  	return bidResponse, nil
   177  }
   178  
   179  func getMediaTypeForImp(impId string, imps []openrtb2.Imp) openrtb_ext.BidType {
   180  	mediaType := openrtb_ext.BidTypeBanner
   181  	for _, imp := range imps {
   182  		if imp.ID == impId {
   183  			if imp.Video != nil {
   184  				mediaType = openrtb_ext.BidTypeVideo
   185  			} else if imp.Native != nil {
   186  				mediaType = openrtb_ext.BidTypeNative
   187  			}
   188  			return mediaType
   189  		}
   190  	}
   191  	return mediaType
   192  }