-
Notifications
You must be signed in to change notification settings - Fork 741
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Adapter: SmartHub #1932
New Adapter: SmartHub #1932
Changes from 3 commits
2573576
e5d4d33
e0b7f6f
e713bba
7a6c090
0f8c117
44ca904
9ec73d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package smarthub | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
|
||
"github.com/prebid/prebid-server/openrtb_ext" | ||
) | ||
|
||
var validParams = []string{ | ||
`{"host":"smarthub.test", "seat":"9Q20EdGxzgWdfPYShScl", "token":"eKmw6alpP3zWQhRCe3flOpz0wpuwRFjW"}`, | ||
} | ||
|
||
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.BidderSmartHub, json.RawMessage(validParam)); err != nil { | ||
t.Errorf("Schema rejected smarthub params: %s", validParam) | ||
} | ||
} | ||
} | ||
|
||
var invalidParams = []string{ | ||
``, | ||
`null`, | ||
`true`, | ||
`5`, | ||
`[]`, | ||
`{}`, | ||
`{"anyparam": "anyvalue"}`, | ||
`{"host":"smarthub.test"}`, | ||
`{"seat":"9Q20EdGxzgWdfPYShScl"}`, | ||
`{"token":"Y9Evrh40ejsrCR4EtidUt1cSxhJsz8X1"}`, | ||
`{"seat":"9Q20EdGxzgWdfPYShScl", "token":"alNYtemWggraDVbhJrsOs9pXc3Eld32E"}`, | ||
`{"host":"smarthub.test", "token":"LNywdP2ebX5iETF8gvBeEoB6Cam64eeq"}`, | ||
`{"host":"smarthub.test", "seat":"9Q20EdGxzgWdfPYShScl"}`, | ||
} | ||
|
||
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.BidderSmartHub, json.RawMessage(invalidParam)); err == nil { | ||
t.Errorf("Schema allowed unexpected params: %s", invalidParam) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
package smarthub | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"text/template" | ||
|
||
"github.com/mxmCherry/openrtb/v15/openrtb2" | ||
"github.com/prebid/prebid-server/adapters" | ||
"github.com/prebid/prebid-server/config" | ||
"github.com/prebid/prebid-server/errortypes" | ||
"github.com/prebid/prebid-server/macros" | ||
"github.com/prebid/prebid-server/openrtb_ext" | ||
) | ||
|
||
const ( | ||
ADAPTER_VER = "1.0.0" | ||
) | ||
|
||
type adapter struct { | ||
endpoint template.Template | ||
} | ||
|
||
type bidExt struct { | ||
MediaType string `json:"mediaType"` | ||
} | ||
|
||
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { | ||
template, err := template.New("endpointTemplate").Parse(config.Endpoint) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) | ||
} | ||
|
||
bidder := &adapter{ | ||
endpoint: *template, | ||
} | ||
|
||
return bidder, nil | ||
} | ||
|
||
func (a *adapter) getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtSmartHub, error) { | ||
var bidderExt adapters.ExtImpBidder | ||
if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { | ||
return nil, &errortypes.BadInput{ | ||
Message: "Bidder extension not provided or can't be unmarshalled", | ||
} | ||
} | ||
|
||
var smarthubExt openrtb_ext.ExtSmartHub | ||
if err := json.Unmarshal(bidderExt.Bidder, &smarthubExt); err != nil { | ||
return nil, &errortypes.BadInput{ | ||
Message: "Error while unmarshaling bidder extension", | ||
} | ||
} | ||
|
||
return &smarthubExt, nil | ||
} | ||
|
||
func (a *adapter) buildEndpointURL(params *openrtb_ext.ExtSmartHub) (string, error) { | ||
endpointParams := macros.EndpointTemplateParams{ | ||
Host: params.Host, | ||
AccountID: params.Seat, | ||
SourceId: params.Token, | ||
} | ||
return macros.ResolveMacros(a.endpoint, endpointParams) | ||
} | ||
|
||
func (a *adapter) MakeRequests( | ||
openRTBRequest *openrtb2.BidRequest, | ||
reqInfo *adapters.ExtraRequestInfo, | ||
) ( | ||
requestsToBidder []*adapters.RequestData, | ||
errs []error, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the reason behind naming output parameters? In There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no reason. I've removed in both |
||
) { | ||
if len(openRTBRequest.Imp) == 0 { | ||
return nil, []error{&errortypes.BadInput{Message: "Missing Imp object"}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick: Prebid server core filters out requests with empty There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed this |
||
} | ||
|
||
var smarthubExt *openrtb_ext.ExtSmartHub | ||
smarthubExt, err := a.getImpressionExt(&(openRTBRequest.Imp[0])) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
url, err := a.buildEndpointURL(smarthubExt) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
reqJSON, err := json.Marshal(openRTBRequest) | ||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json;charset=utf-8") | ||
headers.Add("Accept", "application/json") | ||
headers.Add("Prebid-Adapter-Ver", ADAPTER_VER) | ||
|
||
return []*adapters.RequestData{{ | ||
Method: http.MethodPost, | ||
Body: reqJSON, | ||
Uri: url, | ||
Headers: headers, | ||
}}, nil | ||
} | ||
|
||
func (a *adapter) MakeBids( | ||
openRTBRequest *openrtb2.BidRequest, | ||
requestToBidder *adapters.RequestData, | ||
bidderRawResponse *adapters.ResponseData, | ||
) ( | ||
bidderResponse *adapters.BidderResponse, | ||
errs []error, | ||
) { | ||
if bidderRawResponse.StatusCode == http.StatusNoContent { | ||
return nil, nil | ||
} | ||
|
||
if bidderRawResponse.StatusCode == http.StatusBadRequest { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: fmt.Sprintf("Bad Request. %s", string(bidderRawResponse.Body)), | ||
}} | ||
} | ||
|
||
if bidderRawResponse.StatusCode == http.StatusServiceUnavailable { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: "Bidder unavailable. Please contact the bidder support.", | ||
}} | ||
} | ||
|
||
if bidderRawResponse.StatusCode != http.StatusOK { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Status Code: [ %d ] %s", bidderRawResponse.StatusCode, string(bidderRawResponse.Body)), | ||
}} | ||
} | ||
|
||
responseBody := bidderRawResponse.Body | ||
var bidResp openrtb2.BidResponse | ||
if err := json.Unmarshal(responseBody, &bidResp); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
if len(bidResp.SeatBid) == 0 { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: "Array SeatBid cannot be empty", | ||
}} | ||
} | ||
|
||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(1) | ||
|
||
bids := bidResp.SeatBid[0].Bid | ||
|
||
if len(bids) == 0 { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: "Array SeatBid[0].Bid cannot be empty", | ||
}} | ||
} | ||
|
||
bid := bids[0] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it always only one bid in response? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we don't support more than one bid in response |
||
|
||
var bidExt bidExt | ||
var bidType openrtb_ext.BidType | ||
|
||
if err := json.Unmarshal(bid.Ext, &bidExt); err != nil { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: "Field BidExt is required", | ||
}} | ||
} | ||
|
||
bidType, err := getBidType(bidExt) | ||
|
||
if err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ | ||
Bid: &bid, | ||
BidType: bidType, | ||
}) | ||
return bidResponse, nil | ||
} | ||
|
||
func getBidType(ext bidExt) (openrtb_ext.BidType, error) { | ||
return openrtb_ext.ParseBidType(ext.MediaType) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package smarthub | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/prebid/prebid-server/adapters/adapterstest" | ||
"github.com/prebid/prebid-server/config" | ||
"github.com/prebid/prebid-server/openrtb_ext" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestJsonSamples(t *testing.T) { | ||
bidder, buildErr := Builder(openrtb_ext.BidderSmartHub, config.Adapter{ | ||
Endpoint: "http://{{.Host}}/?seat={{.AccountID}}&token={{.SourceId}}"}) | ||
|
||
assert.NoError(t, buildErr) | ||
adapterstest.RunJSONBidderTest(t, "smarthubtest", bidder) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you pass all three parameters to your URL. Do you need all three to NOT be empty? As of right now, you marked them as
required
insidestatic/bidder-params/smarthub.json
but they can still be zero-lenght strings. In case you need that any or all three of your parameters to not be empty you could add theminLength
property like:Without the additions shown above, an all empty parameter
req.Imp[i].Ext
would be allowed. In other words, for the moment, a test case like this is currently passing:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's what you intended, it's fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks a lot for pointing the mistake! All three parameters mustn't be an empty string. I've fixed this in
static/bidder-params/smarthub.json
and also added possible cases to test intoinvalidParams