-
Notifications
You must be signed in to change notification settings - Fork 742
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Aurélien Giudici
committed
Dec 2, 2020
1 parent
36c497f
commit 1921164
Showing
23 changed files
with
1,291 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,190 @@ | ||
package adot | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/buger/jsonparser" | ||
"github.com/prebid/prebid-server/config" | ||
"net/http" | ||
"net/url" | ||
"strconv" | ||
|
||
"github.com/mxmCherry/openrtb" | ||
"github.com/prebid/prebid-server/adapters" | ||
"github.com/prebid/prebid-server/errortypes" | ||
"github.com/prebid/prebid-server/openrtb_ext" | ||
) | ||
|
||
type AdotAdapter struct { | ||
endpoint string | ||
} | ||
|
||
// NewGridBidder configure bidder endpoint | ||
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter) (adapters.Bidder, error) { | ||
_, err := url.ParseRequestURI(config.Endpoint) | ||
if len(config.Endpoint) > 0 && err != nil { | ||
return nil, fmt.Errorf("unable to parse endpoint url: %v", err) | ||
} | ||
|
||
bidder := &AdotAdapter{ | ||
endpoint: config.Endpoint, | ||
} | ||
return bidder, nil | ||
} | ||
|
||
// MakeRequests makes the HTTP requests which should be made to fetch bids. | ||
func (a *AdotAdapter) MakeRequests(request *openrtb.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { | ||
var errors = make([]error, 0) | ||
|
||
reqJSON, err := json.Marshal(request) | ||
if err != nil { | ||
errors = append(errors, err) | ||
return nil, errors | ||
} | ||
reqJSON = addParallaxIfNecessary(reqJSON) | ||
|
||
headers := http.Header{} | ||
headers.Add("Content-Type", "application/json;charset=utf-8") | ||
|
||
return []*adapters.RequestData{{ | ||
Method: "POST", | ||
Uri: a.endpoint, | ||
Body: reqJSON, | ||
Headers: headers, | ||
}}, errors | ||
} | ||
|
||
// MakeBids unpacks the server's response into Bids. | ||
func (a *AdotAdapter) MakeBids(internalRequest *openrtb.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { | ||
if response.StatusCode == http.StatusNoContent { | ||
return nil, nil | ||
} | ||
|
||
if response.StatusCode == http.StatusBadRequest { | ||
return nil, []error{&errortypes.BadInput{ | ||
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), | ||
}} | ||
} | ||
|
||
if response.StatusCode != http.StatusOK { | ||
return nil, []error{&errortypes.BadServerResponse{ | ||
Message: fmt.Sprintf("Unexpected status code: %d. Run with request.debug = 1 for more info", response.StatusCode), | ||
}} | ||
} | ||
|
||
var bidResp openrtb.BidResponse | ||
if err := json.Unmarshal(response.Body, &bidResp); err != nil { | ||
return nil, []error{err} | ||
} | ||
|
||
bidResponse := adapters.NewBidderResponseWithBidsCapacity(1) | ||
|
||
for _, sb := range bidResp.SeatBid { | ||
for i := range sb.Bid { | ||
if bidType, err := getMediaTypeForBid(&sb.Bid[i], internalRequest); err == nil { | ||
bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ | ||
Bid: &sb.Bid[i], | ||
BidType: bidType, | ||
}) | ||
} | ||
} | ||
} | ||
return bidResponse, nil | ||
|
||
} | ||
|
||
// getMediaTypeForBid determines which type of bid. | ||
func getMediaTypeForBid(bid *openrtb.Bid, internalRequest *openrtb.BidRequest) (openrtb_ext.BidType, error) { | ||
if bid == nil || internalRequest == nil { | ||
return "", fmt.Errorf("the bid request object is nil") | ||
} | ||
|
||
impID := bid.ImpID | ||
|
||
for _, imp := range internalRequest.Imp { | ||
if imp.ID == impID { | ||
if imp.Banner != nil { | ||
return openrtb_ext.BidTypeBanner, nil | ||
} else if imp.Video != nil { | ||
return openrtb_ext.BidTypeVideo, nil | ||
} else if imp.Audio != nil { | ||
return openrtb_ext.BidTypeAudio, nil | ||
} else if imp.Native != nil { | ||
return openrtb_ext.BidTypeNative, nil | ||
} | ||
} | ||
} | ||
|
||
return "", fmt.Errorf("unrecognized bid type in response from adot") | ||
} | ||
|
||
func addParallaxIfNecessary(reqJSON []byte) []byte { | ||
var adotJSON []byte | ||
var err error | ||
|
||
adotRequest, parallaxError := addParallaxInRequest(reqJSON) | ||
if parallaxError == nil { | ||
adotJSON, err = json.Marshal(adotRequest) | ||
if err != nil { | ||
adotJSON = reqJSON | ||
} | ||
} else { | ||
adotJSON = reqJSON | ||
} | ||
|
||
return adotJSON | ||
} | ||
|
||
func addParallaxInRequest(data []byte) (map[string]interface{}, error) { | ||
var adotRequest map[string]interface{} | ||
|
||
if err := json.Unmarshal(data, &adotRequest); err != nil { | ||
return adotRequest, err | ||
} | ||
|
||
imps := adotRequest["imp"].([]interface{}) | ||
for i, impObj := range imps { | ||
castedImps := impObj.(map[string]interface{}) | ||
if isParallaxInExt(castedImps) { | ||
if impByte, err := json.Marshal(impObj); err == nil { | ||
if val, err := jsonparser.Set(impByte, jsonparser.StringToBytes(strconv.FormatBool(true)), "banner", "parallax"); err == nil { | ||
_ = json.Unmarshal(val, &imps[i]) | ||
} | ||
} | ||
} | ||
} | ||
return adotRequest, nil | ||
} | ||
|
||
func isParallaxInExt(impObj map[string]interface{}) bool { | ||
isParallaxInExt := false | ||
|
||
isParallaxByte, err := getParallaxByte(impObj) | ||
if err == nil { | ||
isParallaxInt, err := jsonparser.GetInt(isParallaxByte) | ||
if err != nil { | ||
isParallaxBool, err := jsonparser.GetBoolean(isParallaxByte) | ||
if err == nil { | ||
return isParallaxBool | ||
} | ||
} | ||
isParallaxInExt = isParallaxInt == 1 | ||
} | ||
|
||
return isParallaxInExt | ||
} | ||
|
||
func getParallaxByte(impObj map[string]interface{}) ([]byte, error) { | ||
impByte, err := json.Marshal(impObj) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
isExtByte, _, _, err := jsonparser.Get(impByte, "ext") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
isParallaxByte, _, _, err := jsonparser.Get(isExtByte, "bidder", "parallax") | ||
return isParallaxByte, err | ||
} |
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,125 @@ | ||
package adot | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/mxmCherry/openrtb" | ||
"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" | ||
"io/ioutil" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
var jsonBidReq = getJsonByteForTesting("./static/adapter/adot/parallax_request_test.json") | ||
|
||
func getJsonByteForTesting(path string) []byte { | ||
jsonBidReq, err := ioutil.ReadFile(path) | ||
if err != nil { | ||
fmt.Println("File reading error", err) | ||
return nil | ||
} | ||
|
||
return jsonBidReq | ||
} | ||
|
||
func TestJsonSamples(t *testing.T) { | ||
bidder, buildErr := Builder(openrtb_ext.BidderAdot, config.Adapter{ | ||
Endpoint: "https://dsp.adotmob.com/headerbidding/bidrequest"}) | ||
|
||
if buildErr != nil { | ||
t.Fatalf("Builder returned unexpected error %v", buildErr) | ||
} | ||
|
||
adapterstest.RunJSONBidderTest(t, "adottest", bidder) | ||
} | ||
|
||
func TestEndpoint(t *testing.T) { | ||
_, buildErr := Builder(openrtb_ext.BidderAdot, config.Adapter{ | ||
Endpoint: "wrongurl."}) | ||
|
||
assert.Error(t, buildErr) | ||
} | ||
|
||
// Test the request with the parallax parameter | ||
func TestRequestWithParallax(t *testing.T) { | ||
var bidReq *openrtb.BidRequest | ||
if err := json.Unmarshal(jsonBidReq, &bidReq); err != nil { | ||
fmt.Println("error: ", err.Error()) | ||
} | ||
|
||
reqJSON, err := json.Marshal(bidReq) | ||
if err != nil { | ||
t.Errorf("The request should not be the same, because their is a parallax param in ext.") | ||
} | ||
|
||
adotJson := addParallaxIfNecessary(reqJSON) | ||
stringReqJSON := string(adotJson) | ||
|
||
if stringReqJSON == string(reqJSON) { | ||
t.Errorf("The request should not be the same, because their is a parallax param in ext.") | ||
} | ||
|
||
if strings.Count(stringReqJSON, "parallax: true") == 2 { | ||
t.Errorf("The parallax was not well add in the request") | ||
} | ||
} | ||
|
||
// Test the request without the parallax parameter | ||
func TestRequestWithoutParallax(t *testing.T) { | ||
stringBidReq := strings.Replace(string(jsonBidReq), "\"parallax\": true", "", -1) | ||
jsonReq := []byte(stringBidReq) | ||
|
||
reqJSON := addParallaxIfNecessary(jsonReq) | ||
|
||
if strings.Contains(string(reqJSON), "parallax") { | ||
t.Errorf("The request should not contains parallax param " + string(reqJSON)) | ||
} | ||
} | ||
|
||
// Test the parallax with an invalid request | ||
func TestParallaxWithInvalidRequest(t *testing.T) { | ||
test := map[string]interface{}(nil) | ||
|
||
_, err := getParallaxByte(test) | ||
|
||
assert.Error(t, err) | ||
} | ||
|
||
//Test the media type error | ||
func TestMediaTypeError(t *testing.T) { | ||
_, err := getMediaTypeForBid(nil, nil) | ||
|
||
assert.Error(t, err) | ||
} | ||
|
||
//Test the media type for a bid response | ||
func TestMediaTypeForBid(t *testing.T) { | ||
_, err := getMediaTypeForBid(nil, nil) | ||
|
||
assert.Error(t, err) | ||
|
||
var reqBanner, reqVideo *openrtb.BidRequest | ||
var bidBanner, bidVideo *openrtb.Bid | ||
|
||
err1 := json.Unmarshal(getJsonByteForTesting("./static/adapter/adot/parallax_request_test.json"), &reqBanner) | ||
err2 := json.Unmarshal(getJsonByteForTesting("./static/adapter/adot/parallax_response_test.json"), &bidBanner) | ||
err3 := json.Unmarshal(getJsonByteForTesting("./static/adapter/adot/video_request_test.json"), &reqVideo) | ||
err4 := json.Unmarshal(getJsonByteForTesting("./static/adapter/adot/video_request_test.json"), &bidVideo) | ||
|
||
if err1 != nil || err2 != nil || err3 != nil || err4 != nil { | ||
fmt.Println("error: ", "cannot unmarshal well") | ||
} | ||
|
||
bidType, err := getMediaTypeForBid(bidBanner, reqBanner) | ||
if bidType == openrtb_ext.BidTypeBanner { | ||
t.Errorf("the type is not the valid one. actual: %v, expected: %v", bidType, openrtb_ext.BidTypeBanner) | ||
} | ||
|
||
bidType2, _ := getMediaTypeForBid(bidVideo, reqVideo) | ||
if bidType2 == openrtb_ext.BidTypeVideo { | ||
t.Errorf("the type is not the valid one. actual: %v, expected: %v", bidType2, openrtb_ext.BidTypeVideo) | ||
} | ||
} |
Oops, something went wrong.