github.com/prebid/prebid-server@v0.275.0/endpoints/info/bidders_detail.go (about) 1 package info 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "strings" 8 9 "github.com/golang/glog" 10 "github.com/julienschmidt/httprouter" 11 "github.com/prebid/prebid-server/config" 12 "github.com/prebid/prebid-server/openrtb_ext" 13 ) 14 15 const ( 16 statusActive string = "ACTIVE" 17 statusDisabled string = "DISABLED" 18 ) 19 20 // NewBiddersDetailEndpoint builds a handler for the /info/bidders/<bidder> endpoint. 21 func NewBiddersDetailEndpoint(bidders config.BidderInfos, aliases map[string]string) httprouter.Handle { 22 responses, err := prepareBiddersDetailResponse(bidders, aliases) 23 if err != nil { 24 glog.Fatalf("error creating /info/bidders/<bidder> endpoint response: %v", err) 25 } 26 27 return func(w http.ResponseWriter, _ *http.Request, ps httprouter.Params) { 28 bidder := ps.ByName("bidderName") 29 30 if response, ok := responses[bidder]; ok { 31 w.Header().Set("Content-Type", "application/json") 32 if _, err := w.Write(response); err != nil { 33 glog.Errorf("error writing response to /info/bidders/%s: %v", bidder, err) 34 } 35 } else { 36 w.WriteHeader(http.StatusNotFound) 37 } 38 } 39 } 40 41 func prepareBiddersDetailResponse(bidders config.BidderInfos, aliases map[string]string) (map[string][]byte, error) { 42 details, err := mapDetails(bidders, aliases) 43 if err != nil { 44 return nil, err 45 } 46 47 responses, err := marshalDetailsResponse(details) 48 if err != nil { 49 return nil, err 50 } 51 52 all, err := marshalAllResponse(responses) 53 if err != nil { 54 return nil, err 55 } 56 responses["all"] = all 57 58 return responses, nil 59 } 60 61 func mapDetails(bidders config.BidderInfos, aliases map[string]string) (map[string]bidderDetail, error) { 62 details := map[string]bidderDetail{} 63 64 for bidderName, bidderInfo := range bidders { 65 details[bidderName] = mapDetailFromConfig(bidderInfo) 66 } 67 68 for aliasName, bidderName := range aliases { 69 aliasBaseInfo, aliasBaseInfoFound := details[bidderName] 70 if !aliasBaseInfoFound { 71 return nil, fmt.Errorf("base adapter %s for alias %s not found", bidderName, aliasName) 72 } 73 74 aliasInfo := aliasBaseInfo 75 aliasInfo.AliasOf = bidderName 76 details[aliasName] = aliasInfo 77 } 78 79 return details, nil 80 } 81 82 func marshalDetailsResponse(details map[string]bidderDetail) (map[string][]byte, error) { 83 responses := map[string][]byte{} 84 85 for bidder, detail := range details { 86 json, err := json.Marshal(detail) 87 if err != nil { 88 return nil, fmt.Errorf("unable to marshal info for bidder %s: %v", bidder, err) 89 } 90 responses[bidder] = json 91 } 92 93 return responses, nil 94 } 95 96 func marshalAllResponse(responses map[string][]byte) ([]byte, error) { 97 responsesJSON := make(map[string]json.RawMessage, len(responses)) 98 99 for k, v := range responses { 100 responsesJSON[k] = json.RawMessage(v) 101 } 102 103 json, err := json.Marshal(responsesJSON) 104 if err != nil { 105 return nil, fmt.Errorf("unable to marshal info for bidder all: %v", err) 106 } 107 return json, nil 108 } 109 110 type bidderDetail struct { 111 Status string `json:"status"` 112 UsesHTTPS *bool `json:"usesHttps,omitempty"` 113 Maintainer *maintainer `json:"maintainer,omitempty"` 114 Capabilities *capabilities `json:"capabilities,omitempty"` 115 AliasOf string `json:"aliasOf,omitempty"` 116 } 117 118 type maintainer struct { 119 Email string `json:"email"` 120 } 121 122 type capabilities struct { 123 App *platform `json:"app,omitempty"` 124 Site *platform `json:"site,omitempty"` 125 } 126 127 type platform struct { 128 MediaTypes []string `json:"mediaTypes"` 129 } 130 131 func mapDetailFromConfig(c config.BidderInfo) bidderDetail { 132 var bidderDetail bidderDetail 133 134 if c.Maintainer != nil { 135 bidderDetail.Maintainer = &maintainer{ 136 Email: c.Maintainer.Email, 137 } 138 } 139 140 if c.IsEnabled() { 141 bidderDetail.Status = statusActive 142 143 usesHTTPS := strings.HasPrefix(strings.ToLower(c.Endpoint), "https://") 144 bidderDetail.UsesHTTPS = &usesHTTPS 145 146 if c.Capabilities != nil { 147 bidderDetail.Capabilities = &capabilities{} 148 149 if c.Capabilities.App != nil { 150 bidderDetail.Capabilities.App = &platform{ 151 MediaTypes: mapMediaTypes(c.Capabilities.App.MediaTypes), 152 } 153 } 154 155 if c.Capabilities.Site != nil { 156 bidderDetail.Capabilities.Site = &platform{ 157 MediaTypes: mapMediaTypes(c.Capabilities.Site.MediaTypes), 158 } 159 } 160 } 161 } else { 162 bidderDetail.Status = statusDisabled 163 } 164 165 return bidderDetail 166 } 167 168 func mapMediaTypes(m []openrtb_ext.BidType) []string { 169 mediaTypes := make([]string, len(m)) 170 171 for i, v := range m { 172 mediaTypes[i] = string(v) 173 } 174 175 return mediaTypes 176 }