github.com/prebid/prebid-server@v0.275.0/endpoints/info/bidders.go (about)

     1  package info
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/golang/glog"
    10  	"github.com/julienschmidt/httprouter"
    11  	"github.com/prebid/prebid-server/config"
    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 json.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 json.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  
   139  	return json.Marshal(bidderNames)
   140  }
   141  
   142  func prepareBiddersResponseEnabledOnlyBaseOnly(bidders config.BidderInfos) ([]byte, error) {
   143  	bidderNames := make([]string, 0, len(bidders))
   144  
   145  	for name, info := range bidders {
   146  		if info.IsEnabled() && len(info.AliasOf) == 0 {
   147  			bidderNames = append(bidderNames, name)
   148  		}
   149  	}
   150  
   151  	sort.Strings(bidderNames)
   152  	return json.Marshal(bidderNames)
   153  }
   154  
   155  func writeBadRequest(w http.ResponseWriter, data []byte) {
   156  	w.WriteHeader(http.StatusBadRequest)
   157  	writeWithErrorHandling(w, data)
   158  }
   159  
   160  func writeResponse(w http.ResponseWriter, data []byte) {
   161  	w.Header().Set("Content-Type", "application/json")
   162  	writeWithErrorHandling(w, data)
   163  }
   164  
   165  func writeWithErrorHandling(w http.ResponseWriter, data []byte) {
   166  	if _, err := w.Write(data); err != nil {
   167  		glog.Errorf("error writing response to /info/bidders: %v", err)
   168  	}
   169  }