-
Notifications
You must be signed in to change notification settings - Fork 753
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 in RAD/app_prebid-server-spotx from add_spotx_a…
…dapter to master Squashed commit of the following: commit 4a0d4c64c36903fc56f029f5b646cdace895139e Author: Cameron Rice <cameron.l.rice@gmail.com> Date: Wed Jul 22 11:10:00 2020 -0400 Cleaning up 204 case and updating bidder-info for media type commit eb5a31065ee342e08670f207a726f54baf382cb2 Author: Cameron Rice <cameron.l.rice@gmail.com> Date: Mon Jul 20 16:49:09 2020 -0400 Re-adding unmarshal error check commit 184602b99076a5efd71ad77f4ab22522ad379296 Author: Cameron Rice <cameron.l.rice@gmail.com> Date: Mon Jul 20 13:13:08 2020 -0400 Adding unit tests to increase coverage commit 424c36850ebcfe0e72e240c8d060c715eb0fcd44 Author: Cameron Rice <cameron.l.rice@gmail.com> Date: Fri Jul 17 15:23:24 2020 -0400 Further updates from code review comments * Code clean up * Added macro to endpoint URL * Renamed test file for better description commit 0a44211706a15b2df3b4c13887b43ef3b5be2b6e Author: Cameron Rice <cameron.l.rice@gmail.com> Date: Thu Jul 16 17:46:11 2020 -0400 Updates from code review comments * Removed license file * Cleaned up adapter code * Updated maintainer commit 4e84c38a9207ae64989e135e0f95800d069fd703 Author: Cameron Rice <cameron.l.rice@gmail.com> Date: Wed Jul 15 18:24:40 2020 -0400 Initial commit for adapter
- Loading branch information
Hans Hjort
committed
Jul 22, 2020
1 parent
034928e
commit 31b3857
Showing
20 changed files
with
1,033 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package spotx | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/prebid/prebid-server/openrtb_ext" | ||
) | ||
|
||
func TestValidParams(t *testing.T) { | ||
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") | ||
if err != nil { | ||
t.Fatalf("Failed to fetch the json-schemas. %v", err) | ||
} | ||
|
||
for _, validParam := range validParams { | ||
if err := validator.Validate(openrtb_ext.BidderSpotX, json.RawMessage(validParam)); err != nil { | ||
t.Errorf("Schema rejected spotx params: %s", validParam) | ||
} | ||
} | ||
} | ||
|
||
func TestInvalidParams(t *testing.T) { | ||
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") | ||
if err != nil { | ||
t.Fatalf("Failed to fetch the json-schemas. %v", err) | ||
} | ||
|
||
for _, invalidParam := range invalidParams { | ||
if err := validator.Validate(openrtb_ext.BidderSpotX, json.RawMessage(invalidParam)); err == nil { | ||
t.Errorf("Schema allowed unexpected params: %s", invalidParam) | ||
} | ||
} | ||
} | ||
|
||
var validParams = []string{ | ||
`{"channel_id":"123", "publisher_id":"456"}`, | ||
} | ||
|
||
var invalidParams = []string{ | ||
``, | ||
`null`, | ||
`true`, | ||
`5`, | ||
`4.2`, | ||
`[]`, | ||
`{}`, | ||
`{"channel_id":"123"}`, | ||
`{"publisher_id":"123"}`, | ||
`{"channel_id":"123", "publisher_id":456}`, | ||
`{"channel_id":123, "publisher_id":"456"}`, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
package spotx | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"strconv" | ||
"strings" | ||
"text/template" | ||
|
||
"github.com/golang/glog" | ||
"github.com/mxmCherry/openrtb" | ||
"github.com/prebid/prebid-server/adapters" | ||
"github.com/prebid/prebid-server/errortypes" | ||
"github.com/prebid/prebid-server/macros" | ||
"github.com/prebid/prebid-server/openrtb_ext" | ||
) | ||
|
||
type SpotXAdapter struct { | ||
EndpointTemplate template.Template | ||
} | ||
|
||
type SpotXReqExt struct { | ||
NumberOfAds int `json:"number_of_ads"` | ||
ChannelID string `json:"channel_id"` | ||
} | ||
|
||
type SpotXBidExt struct { | ||
Duration int `json:"duration"` | ||
Tier string `json:"tier"` | ||
} | ||
|
||
func (a *SpotXAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
if len(request.Imp) == 0 { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: "Request must have at least one Imp", | ||
}} | ||
} | ||
|
||
var bidderExt adapters.ExtImpBidder | ||
if err := json.Unmarshal(request.Imp[0].Ext, &bidderExt); err != nil { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: err.Error(), | ||
}} | ||
} | ||
|
||
var spotXExt openrtb_ext.ExtImpSpotX | ||
if err := json.Unmarshal(bidderExt.Bidder, &spotXExt); err != nil { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: err.Error(), | ||
}} | ||
} | ||
|
||
if len(spotXExt.ChannelID) == 0 { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: "Channel ID must be provided in bidder configuration", | ||
}} | ||
} | ||
|
||
if len(spotXExt.PublisherID) == 0 { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: "Publisher ID must be provided in bidder configuration", | ||
}} | ||
} | ||
|
||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json;charset=utf-8") | ||
headers.Add("Accept", "application/json") | ||
|
||
uri, err := a.buildEndpointURI(&spotXExt) | ||
if err != nil { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: err.Error(), | ||
}} | ||
} | ||
|
||
spotXReqExt := SpotXReqExt{ | ||
NumberOfAds: len(request.Imp), | ||
ChannelID: spotXExt.ChannelID, | ||
} | ||
|
||
spotXReqExtJSON, err := json.Marshal(spotXReqExt) | ||
if err != nil { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: err.Error(), | ||
}} | ||
} | ||
request.Ext = spotXReqExtJSON | ||
|
||
reqJSON, err := json.Marshal(request) | ||
if err != nil { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: err.Error(), | ||
}} | ||
} | ||
|
||
requests := []*adapters.RequestData{ | ||
{ | ||
Method: "POST", | ||
Uri: uri, | ||
Body: reqJSON, | ||
Headers: headers, | ||
}, | ||
} | ||
|
||
return requests, nil | ||
} | ||
|
||
// Builds endpoint url based on adapter-specific pub settings from imp.ext | ||
func (a *SpotXAdapter) buildEndpointURI(params *openrtb_ext.ExtImpSpotX) (string, error) { | ||
endpointParams := macros.EndpointTemplateParams{PublisherID: params.PublisherID} | ||
return macros.ResolveMacros(a.EndpointTemplate, endpointParams) | ||
} | ||
|
||
func (a *SpotXAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if response.StatusCode == http.StatusNoContent { | ||
errMsg := "204 status code received: Empty response" | ||
// check if the empty response was due to an exception | ||
if _, ok := response.Headers["X-spotx-Exception-RESULT"]; ok { | ||
exceptionID := strings.Join(response.Headers["X-spotx-Exception-0-ID"], ", ") | ||
exceptionMsg := strings.Join(response.Headers["X-spotx-Exception-0-Message"], ", ") | ||
|
||
errMsg = fmt.Sprintf("204 status code received due to failure. Exception ID: %s. Exception Message: %s", exceptionID, exceptionMsg) | ||
} | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: errMsg, | ||
}} | ||
} | ||
|
||
if response.StatusCode != http.StatusOK { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Unexpected status code: %d", response.StatusCode), | ||
}} | ||
} | ||
|
||
var bidResp openrtb.BidResponse | ||
if err := json.Unmarshal(response.Body, &bidResp); err != nil { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: err.Error(), | ||
}} | ||
} | ||
|
||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(5) | ||
|
||
for _, sb := range bidResp.SeatBid { | ||
for i := 0; i < len(sb.Bid); i++ { | ||
bid := sb.Bid[i] | ||
var bidExt SpotXBidExt | ||
if err := json.Unmarshal(bid.Ext, &bidExt); err != nil { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: "Unable to unmarshal bid ext", | ||
}} | ||
} | ||
|
||
if len(bid.Cat) > 0 { | ||
bid.Cat = bid.Cat[0:1] | ||
} else { | ||
//create empty categories array to force bid to be rejected | ||
bid.Cat = []string{} | ||
} | ||
|
||
impVideo := &openrtb_ext.ExtBidPrebidVideo{ | ||
Duration: bidExt.Duration, | ||
} | ||
|
||
bidTier := 0 | ||
if respTier, err := strconv.Atoi(bidExt.Tier); err == nil { | ||
bidTier = respTier | ||
} | ||
|
||
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ | ||
Bid: &bid, | ||
BidVideo: impVideo, | ||
BidType: openrtb_ext.BidTypeVideo, | ||
DealPriority: bidTier, | ||
}) | ||
} | ||
} | ||
|
||
return bidResponse, nil | ||
} | ||
|
||
func NewSpotXAdapter(endpointTemplate string) *SpotXAdapter { | ||
template, err := template.New("endpointTemplate").Parse(endpointTemplate) | ||
if err != nil { | ||
glog.Fatal("Unable to parse endpoint url template") | ||
return nil | ||
} | ||
return &SpotXAdapter{ | ||
EndpointTemplate: *template, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
{ | ||
"mockBidRequest": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"video": { | ||
"mimes": [ | ||
"video/mp4" | ||
], | ||
"minduration": 15, | ||
"maxduration": 30, | ||
"protocols": [ | ||
2, | ||
3, | ||
5, | ||
6, | ||
7, | ||
8 | ||
], | ||
"w": 940, | ||
"h": 560 | ||
}, | ||
"ext": { | ||
"bidder": { | ||
"channel_id": "123", | ||
"publisher_id": "456" | ||
} | ||
} | ||
} | ||
] | ||
}, | ||
"httpCalls": [ | ||
{ | ||
"expectedRequest": { | ||
"uri": "http://search.spotxchange.com/openrtb/2.5/456", | ||
"body": { | ||
"id": "test-request-id", | ||
"imp": [ | ||
{ | ||
"id": "test-imp-id", | ||
"video": { | ||
"mimes": [ | ||
"video/mp4" | ||
], | ||
"minduration": 15, | ||
"maxduration": 30, | ||
"protocols": [ | ||
2, | ||
3, | ||
5, | ||
6, | ||
7, | ||
8 | ||
], | ||
"w": 940, | ||
"h": 560 | ||
}, | ||
"ext": { | ||
"bidder": { | ||
"channel_id": "123", | ||
"publisher_id": "456" | ||
} | ||
} | ||
} | ||
|
||
], | ||
"ext": { | ||
"number_of_ads": 1, | ||
"channel_id": "123" | ||
} | ||
} | ||
}, | ||
"mockResponse": { | ||
"status": 200, | ||
"body": { | ||
"id": "test-request-id", | ||
"seatbid": [ | ||
{ | ||
"seat": "958", | ||
"bid": [ | ||
{ | ||
"id": "7706636740145184841", | ||
"impid": "test-imp-id", | ||
"price": 0.500000, | ||
"adid": "29681110", | ||
"adm": "some-test-ad", | ||
"adomain": [ | ||
"appnexus.com" | ||
], | ||
"iurl": "http://nym1-ib.adnxs.com/cr?id=29681110", | ||
"cid": "958", | ||
"crid": "29681110", | ||
"h": 250, | ||
"w": 300, | ||
"cat": [ | ||
"IAB9-1" | ||
], | ||
"ext": { | ||
"duration": 15, | ||
"tier": "5" | ||
} | ||
} | ||
] | ||
} | ||
], | ||
"bidid": "5778926625248726496", | ||
"cur": "USD" | ||
} | ||
} | ||
} | ||
], | ||
"expectedBidResponses": [ | ||
{ | ||
"currency": "USD", | ||
"bids": [ | ||
{ | ||
"bid": { | ||
"id": "7706636740145184841", | ||
"impid": "test-imp-id", | ||
"price": 0.5, | ||
"adm": "some-test-ad", | ||
"adid": "29681110", | ||
"adomain": [ | ||
"appnexus.com" | ||
], | ||
"iurl": "http://nym1-ib.adnxs.com/cr?id=29681110", | ||
"cid": "958", | ||
"crid": "29681110", | ||
"w": 300, | ||
"h": 250, | ||
"cat": [ | ||
"IAB9-1" | ||
], | ||
"ext": { | ||
"duration": 15, | ||
"tier": "5" | ||
} | ||
}, | ||
"type": "video" | ||
} | ||
] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"channel_id": "123", | ||
"publisher_id": "456" | ||
} |
Oops, something went wrong.