github.com/prebid/prebid-server/v2@v2.18.0/endpoints/info/bidders.go (about)

     1  package info
     2  
     3  import (
     4  	"net/http"
     5  	"sort"
     6  	"strings"
     7  
     8  	"github.com/golang/glog"
     9  	"github.com/julienschmidt/httprouter"
    10  	"github.com/prebid/prebid-server/v2/config"
    11  	"github.com/prebid/prebid-server/v2/util/jsonutil"
    12  )
    13  
    14  var invalidEnabledOnlyMsg = []byte(`Invalid value for 'enabledonly' query param, must be of boolean type`)
    15  var invalidBaseAdaptersOnlyMsg = []byte(`Invalid value for 'baseadaptersonly' query param, must be of boolean type`)
    16  
    17  // NewBiddersEndpoint builds a handler for the /info/bidders endpoint.
    18  func NewBiddersEndpoint(bidders config.BidderInfos, aliases map[string]string) httprouter.Handle {
    19  	responseAll, err := prepareBiddersResponseAll(bidders, aliases)
    20  	if err != nil {
    21  		glog.Fatalf("error creating /info/bidders endpoint all bidders response: %v", err)
    22  	}
    23  
    24  	responseAllBaseOnly, err := prepareBiddersResponseAllBaseOnly(bidders)
    25  	if err != nil {
    26  		glog.Fatalf("error creating /info/bidders endpoint all bidders (base adapters only) response: %v", err)
    27  	}
    28  
    29  	responseEnabledOnly, err := prepareBiddersResponseEnabledOnly(bidders, aliases)
    30  	if err != nil {
    31  		glog.Fatalf("error creating /info/bidders endpoint enabled only response: %v", err)
    32  	}
    33  
    34  	responseEnabledOnlyBaseOnly, err := prepareBiddersResponseEnabledOnlyBaseOnly(bidders)
    35  	if err != nil {
    36  		glog.Fatalf("error creating /info/bidders endpoint enabled only (base adapters only) response: %v", err)
    37  	}
    38  
    39  	return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    40  		enabledOnly, baseAdaptersOnly, errMsg := readQueryFlags(r)
    41  		if errMsg != nil {
    42  			writeBadRequest(w, errMsg)
    43  			return
    44  		}
    45  
    46  		var response []byte
    47  		switch {
    48  		case !enabledOnly && !baseAdaptersOnly:
    49  			response = responseAll
    50  		case !enabledOnly && baseAdaptersOnly:
    51  			response = responseAllBaseOnly
    52  		case enabledOnly && !baseAdaptersOnly:
    53  			response = responseEnabledOnly
    54  		case enabledOnly && baseAdaptersOnly:
    55  			response = responseEnabledOnlyBaseOnly
    56  		}
    57  		writeResponse(w, response)
    58  	}
    59  }
    60  
    61  func readQueryFlags(r *http.Request) (enabledOnly, baseAdaptersOnly bool, errMsg []byte) {
    62  	enabledOnly, ok := readQueryFlag(r, "enabledonly")
    63  	if !ok {
    64  		return false, false, invalidEnabledOnlyMsg
    65  	}
    66  
    67  	baseAdapterOnly, ok := readQueryFlag(r, "baseadaptersonly")
    68  	if !ok {
    69  		return false, false, invalidBaseAdaptersOnlyMsg
    70  	}
    71  
    72  	return enabledOnly, baseAdapterOnly, nil
    73  }
    74  
    75  func readQueryFlag(r *http.Request, queryParam string) (flag, ok bool) {
    76  	q := r.URL.Query()
    77  
    78  	v, exists := q[queryParam]
    79  
    80  	if !exists || len(v) == 0 {
    81  		return false, true
    82  	}
    83  
    84  	switch strings.ToLower(v[0]) {
    85  	case "true":
    86  		return true, true
    87  	case "false":
    88  		return false, true
    89  	default:
    90  		return false, false
    91  	}
    92  }
    93  
    94  func prepareBiddersResponseAll(bidders config.BidderInfos, aliases map[string]string) ([]byte, error) {
    95  	bidderNames := make([]string, 0, len(bidders)+len(aliases))
    96  
    97  	for name := range bidders {
    98  		bidderNames = append(bidderNames, name)
    99  	}
   100  
   101  	for name := range aliases {
   102  		bidderNames = append(bidderNames, name)
   103  	}
   104  
   105  	sort.Strings(bidderNames)
   106  	return jsonutil.Marshal(bidderNames)
   107  }
   108  
   109  func prepareBiddersResponseAllBaseOnly(bidders config.BidderInfos) ([]byte, error) {
   110  	bidderNames := make([]string, 0, len(bidders))
   111  
   112  	for name, info := range bidders {
   113  		if len(info.AliasOf) == 0 {
   114  			bidderNames = append(bidderNames, name)
   115  		}
   116  	}
   117  
   118  	sort.Strings(bidderNames)
   119  	return jsonutil.Marshal(bidderNames)
   120  }
   121  
   122  func prepareBiddersResponseEnabledOnly(bidders config.BidderInfos, aliases map[string]string) ([]byte, error) {
   123  	bidderNames := make([]string, 0, len(bidders)+len(aliases))
   124  
   125  	for name, info := range bidders {
   126  		if info.IsEnabled() {
   127  			bidderNames = append(bidderNames, name)
   128  		}
   129  	}
   130  
   131  	for name, bidder := range aliases {
   132  		if info, ok := bidders[bidder]; ok && info.IsEnabled() {
   133  			bidderNames = append(bidderNames, name)
   134  		}
   135  	}
   136  
   137  	sort.Strings(bidderNames)
   138  	return jsonutil.Marshal(bidderNames)
   139  }
   140  
   141  func prepareBiddersResponseEnabledOnlyBaseOnly(bidders config.BidderInfos) ([]byte, error) {
   142  	bidderNames := make([]string, 0, len(bidders))
   143  
   144  	for name, info := range bidders {
   145  		if info.IsEnabled() && len(info.AliasOf) == 0 {
   146  			bidderNames = append(bidderNames, name)
   147  		}
   148  	}
   149  
   150  	sort.Strings(bidderNames)
   151  	return jsonutil.Marshal(bidderNames)
   152  }
   153  
   154  func writeBadRequest(w http.ResponseWriter, data []byte) {
   155  	w.WriteHeader(http.StatusBadRequest)
   156  	writeWithErrorHandling(w, data)
   157  }
   158  
   159  func writeResponse(w http.ResponseWriter, data []byte) {
   160  	w.Header().Set("Content-Type", "application/json")
   161  	writeWithErrorHandling(w, data)
   162  }
   163  
   164  func writeWithErrorHandling(w http.ResponseWriter, data []byte) {
   165  	if _, err := w.Write(data); err != nil {
   166  		glog.Errorf("error writing response to /info/bidders: %v", err)
   167  	}
   168  }