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 }