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

     1  package logan
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/prebid/openrtb/v20/openrtb2"
     9  	"github.com/prebid/prebid-server/v2/adapters"
    10  	"github.com/prebid/prebid-server/v2/config"
    11  	"github.com/prebid/prebid-server/v2/errortypes"
    12  	"github.com/prebid/prebid-server/v2/openrtb_ext"
    13  )
    14  
    15  type adapter struct {
    16  	endpoint string
    17  }
    18  
    19  type reqBodyExt struct {
    20  	LoganBidderExt reqBodyExtBidder `json:"bidder"`
    21  }
    22  
    23  type reqBodyExtBidder struct {
    24  	Type        string `json:"type"`
    25  	PlacementID string `json:"placementId,omitempty"`
    26  }
    27  
    28  func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
    29  	bidder := &adapter{
    30  		endpoint: config.Endpoint,
    31  	}
    32  	return bidder, nil
    33  }
    34  
    35  func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
    36  	var errors []error
    37  	var adapterRequests []*adapters.RequestData
    38  
    39  	originalImpSlice := request.Imp
    40  
    41  	for i := range originalImpSlice {
    42  		currImp := originalImpSlice[i]
    43  		request.Imp = []openrtb2.Imp{currImp}
    44  
    45  		var bidderExt reqBodyExt
    46  		if err := json.Unmarshal(currImp.Ext, &bidderExt); err != nil {
    47  			errors = append(errors, &errortypes.BadInput{
    48  				Message: err.Error(),
    49  			})
    50  			continue // or return
    51  		}
    52  
    53  		bidderExt.LoganBidderExt.Type = "publisher" // constant
    54  
    55  		finalImpExt, err := json.Marshal(bidderExt)
    56  		if err != nil {
    57  			return nil, append(errors, err)
    58  		}
    59  
    60  		request.Imp[0].Ext = finalImpExt
    61  
    62  		adapterReq, err := a.makeRequest(request)
    63  		if err != nil {
    64  			return nil, append(errors, err)
    65  		}
    66  
    67  		if adapterReq != nil {
    68  			adapterRequests = append(adapterRequests, adapterReq)
    69  		}
    70  	}
    71  	request.Imp = originalImpSlice
    72  	return adapterRequests, nil
    73  }
    74  
    75  func (a *adapter) makeRequest(request *openrtb2.BidRequest) (*adapters.RequestData, error) {
    76  	reqJSON, err := json.Marshal(request)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	headers := http.Header{}
    82  	headers.Add("Content-Type", "application/json;charset=utf-8")
    83  	headers.Add("Accept", "application/json")
    84  	return &adapters.RequestData{
    85  		Method:  "POST",
    86  		Uri:     a.endpoint,
    87  		Body:    reqJSON,
    88  		Headers: headers,
    89  		ImpIDs:  openrtb_ext.GetImpIDs(request.Imp),
    90  	}, nil
    91  }
    92  
    93  func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
    94  	if responseData.StatusCode == http.StatusNoContent {
    95  		return nil, nil
    96  	}
    97  
    98  	if responseData.StatusCode != http.StatusOK {
    99  		err := &errortypes.BadServerResponse{
   100  			Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info.", responseData.StatusCode),
   101  		}
   102  		return nil, []error{err}
   103  	}
   104  
   105  	var response openrtb2.BidResponse
   106  	if err := json.Unmarshal(responseData.Body, &response); err != nil {
   107  		return nil, []error{err}
   108  	}
   109  
   110  	bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
   111  	bidResponse.Currency = response.Cur
   112  
   113  	impsMappedByID := make(map[string]openrtb2.Imp, len(request.Imp))
   114  	for i, imp := range request.Imp {
   115  		impsMappedByID[request.Imp[i].ID] = imp
   116  	}
   117  
   118  	for _, seatBid := range response.SeatBid {
   119  		for i := range seatBid.Bid {
   120  			bidType, err := getMediaTypeForImp(seatBid.Bid[i].ImpID, impsMappedByID)
   121  			if err != nil {
   122  				return nil, []error{err}
   123  			}
   124  
   125  			b := &adapters.TypedBid{
   126  				Bid:     &seatBid.Bid[i],
   127  				BidType: bidType,
   128  			}
   129  			bidResponse.Bids = append(bidResponse.Bids, b)
   130  		}
   131  	}
   132  	return bidResponse, nil
   133  }
   134  
   135  func getMediaTypeForImp(impID string, impMap map[string]openrtb2.Imp) (openrtb_ext.BidType, error) {
   136  	if index, found := impMap[impID]; found {
   137  		if index.Banner != nil {
   138  			return openrtb_ext.BidTypeBanner, nil
   139  		}
   140  		if index.Video != nil {
   141  			return openrtb_ext.BidTypeVideo, nil
   142  		}
   143  		if index.Native != nil {
   144  			return openrtb_ext.BidTypeNative, nil
   145  		}
   146  	}
   147  
   148  	return "", &errortypes.BadInput{
   149  		Message: fmt.Sprintf("Failed to find impression \"%s\"", impID),
   150  	}
   151  }