Skip to content

Commit

Permalink
Merge pull request #923 from PubMatic-OpenWrap/ci
Browse files Browse the repository at this point in the history
RE-3773: Release 3rd-Oct-2024
  • Loading branch information
PubMatic-OpenWrap authored Sep 27, 2024
2 parents 0d8fef1 + 0babd5d commit be2c88b
Show file tree
Hide file tree
Showing 69 changed files with 4,523 additions and 1,666 deletions.
9 changes: 4 additions & 5 deletions adapters/vastbidder/etree_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package vastbidder

import (
"strconv"
"strings"

"github.com/beevik/etree"
"github.com/prebid/prebid-server/v2/openrtb_ext"
Expand Down Expand Up @@ -70,7 +69,7 @@ func (p *etreeXMLParser) GetPricingDetails() (price float64, currency string) {
return 0.0, ""
}

priceValue, err := strconv.ParseFloat(strings.TrimSpace(node.Text()), 64)
priceValue, err := strconv.ParseFloat(node.TrimmedText(), 64)
if nil != err {
return 0.0, ""
}
Expand All @@ -89,7 +88,7 @@ func (p *etreeXMLParser) GetAdvertiser() (advertisers []string) {
if ext.SelectAttrValue("type", "") == "advertiser" {
ele := ext.SelectElement("Advertiser")
if ele != nil {
if value := strings.TrimSpace(ele.Text()); len(value) > 0 {
if value := ele.TrimmedText(); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
Expand All @@ -98,7 +97,7 @@ func (p *etreeXMLParser) GetAdvertiser() (advertisers []string) {

case vastVersion4x:
if ele := p.adElement.SelectElement("Advertiser"); ele != nil {
if value := strings.TrimSpace(ele.Text()); len(value) > 0 {
if value := ele.TrimmedText(); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
Expand Down Expand Up @@ -126,7 +125,7 @@ func (p *etreeXMLParser) GetDuration() (int, error) {
if node == nil {
return 0, errEmptyVideoDuration
}
return parseDuration(strings.TrimSpace(node.Text()))
return parseDuration(node.TrimmedText())
}

func (p *etreeXMLParser) getAdElement(vast *etree.Element) *etree.Element {
Expand Down
6 changes: 6 additions & 0 deletions adapters/vastbidder/etree_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,12 @@ func getPricingDetailsTestCases() []struct {
wantPrice: 0,
wantCurrency: "",
},
{
name: "bug",
vastXML: "<VAST\n\txmlns:xs=\"https://www.w3.org/2001/XMLSchema\"\n\txmlns=\"https://www.iab.com/VAST\" version=\"4.1\">\n\t<Ad id=\"scenario_9_adid\" sequence=\"1\">\n\t\t<InLine>\n\t\t\t<AdSystem version=\"4.1\">PubMatic</AdSystem>\n\t\t\t<AdServingId>scenario_9</AdServingId>\n\t\t\t<AdTitle>Test Ad scenario_9</AdTitle>\n\t\t\t<Pricing model=\"cpm\" currency=\"USD\">\n\t\t\t\t<![CDATA[ 5.00 ]]>\n\t\t\t</Pricing>\n\t\t\t<Impression>\n\t\t\t\t<![CDATA[ https://example.com/impression/ ]]>\n\t\t\t</Impression>\n\t\t\t<Advertiser>Test Advertiser</Advertiser>\n\t\t\t<Category authority=\"https://www.iabtechlab.com/categoryauthority\">IAB1-1\t</Category>\n\t\t\t<Creatives>\n\t\t\t\t<Creative id=\"5481\" sequence=\"1\" adId=\"2447226_scenario_9\">\n\t\t\t\t\t<UniversalAdId idRegistry=\"Ad-ID\">8465_scenario_9</UniversalAdId>\n\t\t\t\t\t<Linear>\n\t\t\t\t\t\t<Duration>00:00:10</Duration>\n\t\t\t\t\t\t<MediaFiles>\n\t\t\t\t\t\t\t<MediaFile delivery=\"progressive\" type=\"video/mp4\" bitrate=\"500\" width=\"400\" height=\"300\" scalable=\"true\" maintainAspectRatio=\"true\">\n\t\t\t\t\t\t\t\t<![CDATA[ https://ads.pubmatic.com/AdServer/js/ott/sampleads/10_seconds_ad.mp4 ]]>\n\t\t\t\t\t\t\t</MediaFile>\n\t\t\t\t\t\t</MediaFiles>\n\t\t\t\t\t</Linear>\n\t\t\t\t</Creative>\n\t\t\t</Creatives>\n\t\t</InLine>\n\t</Ad>\n</VAST> ",
wantPrice: 5,
wantCurrency: "USD",
},
// TODO: Add test cases.
}
}
Expand Down
8 changes: 4 additions & 4 deletions adapters/vastbidder/fastxml_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (p *fastXMLParser) GetPricingDetails() (price float64, currency string) {
return 0.0, ""
}

priceValue, err := strconv.ParseFloat(strings.TrimSpace(p.reader.Text(node, true)), 64)
priceValue, err := strconv.ParseFloat(strings.TrimSpace(p.reader.RawText(node)), 64)
if nil != err {
return 0.0, ""
}
Expand All @@ -89,7 +89,7 @@ func (p *fastXMLParser) GetAdvertiser() (advertisers []string) {
if p.reader.SelectAttrValue(ext, "type") == "advertiser" {
ele := p.reader.SelectElement(ext, "Advertiser")
if ele != nil {
if value := strings.TrimSpace(p.reader.Text(ele, true)); len(value) > 0 {
if value := strings.TrimSpace(p.reader.Text(ele)); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
Expand All @@ -98,7 +98,7 @@ func (p *fastXMLParser) GetAdvertiser() (advertisers []string) {

case vastVersion4x:
if ele := p.reader.SelectElement(p.adElement, "Advertiser"); ele != nil {
if value := strings.TrimSpace(p.reader.Text(ele, true)); len(value) > 0 {
if value := strings.TrimSpace(p.reader.Text(ele)); len(value) > 0 {
advertisers = append(advertisers, value)
}
}
Expand Down Expand Up @@ -126,7 +126,7 @@ func (p *fastXMLParser) GetDuration() (int, error) {
if node == nil {
return 0, errEmptyVideoDuration
}
return parseDuration(strings.TrimSpace(p.reader.Text(node, true)))
return parseDuration(strings.TrimSpace(p.reader.RawText(node)))
}

func (p *fastXMLParser) getAdElement(vast *fastxml.Element) *fastxml.Element {
Expand Down
22 changes: 11 additions & 11 deletions adapters/vastbidder/vastbidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
// VASTBidder is default implementation of ITagBidder
type VASTBidder struct {
adapters.Bidder
bidderName openrtb_ext.BidderName
adapterConfig *config.Adapter
fastXMLExperiment bool
bidderName openrtb_ext.BidderName
adapterConfig *config.Adapter
fastXMLEnabledPercentage int
}

// MakeRequests will contains default definition for processing queries
Expand Down Expand Up @@ -76,7 +76,7 @@ func (a *VASTBidder) MakeBids(internalRequest *openrtb2.BidRequest, externalRequ

responseData, errs := handler.MakeBids()

if a.fastXMLExperiment && len(errs) == 0 {
if openrtb_ext.IsFastXMLEnabled(a.fastXMLEnabledPercentage) && len(errs) == 0 {
a.fastXMLTesting(
newResponseHandler(internalRequest, externalRequest, response, getXMLParser(fastXMLParserType)),
responseData,
Expand All @@ -101,26 +101,26 @@ func (a *VASTBidder) fastXMLTesting(handler *responseHandler, responseData *adap
}
}

vastBidderInfo := &openrtb_ext.FastXMLMetrics{
xmlParsingMetrics := &openrtb_ext.FastXMLMetrics{
XMLParserTime: handlerTime,
EtreeParserTime: etreeParserTime,
IsRespMismatch: isVASTMismatch,
}

responseData.FastXMLMetrics = vastBidderInfo
responseData.FastXMLMetrics = xmlParsingMetrics
}

// NewTagBidder is an constructor for TagBidder
func NewTagBidder(bidderName openrtb_ext.BidderName, config config.Adapter, enableFastXML bool) *VASTBidder {
func NewTagBidder(bidderName openrtb_ext.BidderName, config config.Adapter, enableFastXML int) *VASTBidder {
obj := &VASTBidder{
bidderName: bidderName,
adapterConfig: &config,
fastXMLExperiment: enableFastXML,
bidderName: bidderName,
adapterConfig: &config,
fastXMLEnabledPercentage: enableFastXML,
}
return obj
}

// Builder builds a new instance of the 33Across adapter for the given bidder with the given config.
func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, serverConfig config.Server) (adapters.Bidder, error) {
return NewTagBidder(bidderName, config, serverConfig.EnableFastXML), nil
return NewTagBidder(bidderName, config, serverConfig.FastXMLEnabledPercentage), nil
}
2 changes: 1 addition & 1 deletion adapters/vastbidder/vastbidder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func TestMakeRequests(t *testing.T) {
RegisterNewBidderMacro(bidderName, func() IBidderMacro {
return newMyVastBidderMacro(tt.args.customHeaders)
})
bidder := NewTagBidder(bidderName, config.Adapter{}, false)
bidder := NewTagBidder(bidderName, config.Adapter{}, 0)
reqData, err := bidder.MakeRequests(tt.args.req, nil)
assert.Nil(t, err)
for _, req := range reqData {
Expand Down
8 changes: 4 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,10 +675,10 @@ type Debug struct {
}

type Server struct {
ExternalUrl string
GvlID int
DataCenter string
EnableFastXML bool
ExternalUrl string
GvlID int
DataCenter string
FastXMLEnabledPercentage int
}

func (server *Server) Empty() bool {
Expand Down
8 changes: 4 additions & 4 deletions config/config_ow.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package config

type OpenWrapConfig struct {
// OpenWrap Configurations
EnableFastXML bool `mapstructure:"enable_fast_xml"`
TrackerURL string `mapstructure:"tracker_url"`
VendorListScheduler VendorListScheduler `mapstructure:"vendor_list_scheduler"`
PriceFloorFetcher PriceFloorFetcher `mapstructure:"price_floor_fetcher"`
FastXMLEnabledPercentage int `mapstructure:"fast_xml_enabled_percentage"`
TrackerURL string `mapstructure:"tracker_url"`
VendorListScheduler VendorListScheduler `mapstructure:"vendor_list_scheduler"`
PriceFloorFetcher PriceFloorFetcher `mapstructure:"price_floor_fetcher"`
}

type PriceFloorFetcher struct {
Expand Down
192 changes: 192 additions & 0 deletions endpoints/events/events_ow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package events

import (
"encoding/json"
"net/url"
"strings"

"github.com/golang/glog"
"github.com/prebid/openrtb/v20/openrtb2"
"github.com/prebid/prebid-server/v2/openrtb_ext"
)

// standard VAST macros
// https://interactiveadvertisingbureau.github.io/vast/vast4macros/vast4-macros-latest.html#macro-spec-adcount
const (
VASTAdTypeMacro = "[ADTYPE]" //VASTAdTypeMacro openwrap macro for ADTYPE
VASTAppBundleMacro = "[APPBUNDLE]" //VASTAppBundleMacro openwrap macro for APPBUNDLE
VASTDomainMacro = "[DOMAIN]" //VASTDomainMacro openwrap macro for DOMAIN
VASTPageURLMacro = "[PAGEURL]" //VASTPageURLMacro openwrap macro for PAGEURL
PBSEventIDMacro = "[EVENT_ID]" // PBSEventIDMacro macro for injecting PBS defined video event tracker id
PBSAccountMacro = "[PBS-ACCOUNT]" // PBSAccountMacro represents publisher id / account id
PBSBidderMacro = "[PBS-BIDDER]" // PBSBidderMacro represents bidder name
PBSOrigBidIDMacro = "[PBS-ORIG_BIDID]" // PBSOrigBidIDMacro represents original bid id.
PBSBidIDMacro = "[PBS-BIDID]" // PBSBidIDMacro represents bid id. If auction.generate-bid-id config is on, then resolve with response.seatbid.bid.ext.prebid.bidid. Else replace with response.seatbid.bid.id
PBSAdvertiserNameMacro = "[ADVERTISER_NAME]" // [ADERVERTISER_NAME] represents advertiser name
PBSAdUnitIDMacro = "[AD_UNIT]" // PBSAdUnitIDMacro Pass imp.tagId using this macro
PBSBidderCodeMacro = "[BIDDER_CODE]" // PBSBidderCodeMacro represents an alias id or core bidder id.
)

// PubMatic specific event IDs
// This will go in event-config once PreBid modular design is in place
var trackingEventIDMap = map[string]string{
"start": "2",
"firstQuartile": "4",
"midpoint": "3",
"thirdQuartile": "5",
"complete": "6",
}

var trackingEvents = []string{"start", "firstQuartile", "midpoint", "thirdQuartile", "complete"}

// GetVideoEventTracking returns map containing key as event name value as associaed video event tracking URL
// By default PBS will expect [EVENT_ID] macro in trackerURL to inject event information
// [EVENT_ID] will be injected with one of the following values
//
// firstQuartile, midpoint, thirdQuartile, complete
//
// If your company can not use [EVENT_ID] and has its own macro. provide config.TrackerMacros implementation
// and ensure that your macro is part of trackerURL configuration
// GetVideoEventTracking returns map containing key as event name value as associaed video event tracking URL
// By default PBS will expect [EVENT_ID] macro in trackerURL to inject event information
// [EVENT_ID] will be injected with one of the following values
//
// firstQuartile, midpoint, thirdQuartile, complete
//
// If your company can not use [EVENT_ID] and has its own macro. provide config.TrackerMacros implementation
// and ensure that your macro is part of trackerURL configuration
func GetVideoEventTracking(
req *openrtb2.BidRequest,
imp *openrtb2.Imp,
bid *openrtb2.Bid,
trackerURL string,
prebidGenBidId, requestingBidder, bidderCoreName string,
timestamp int64) map[string]string {

if req == nil || imp == nil || bid == nil || strings.TrimSpace(trackerURL) == "" {
return nil
}

// replace standard macros
// NYC shall we put all macros with their default values here?
macroMap := map[string]string{
PBSAdUnitIDMacro: imp.TagID,
PBSBidIDMacro: bid.ID,
PBSOrigBidIDMacro: bid.ID,
PBSBidderMacro: bidderCoreName,
PBSBidderCodeMacro: requestingBidder,
PBSAdvertiserNameMacro: "",
VASTAdTypeMacro: string(openrtb_ext.BidTypeVideo),
}

/* Use generated bidId if present, else use bid.ID */
if len(prebidGenBidId) > 0 && prebidGenBidId != bid.ID {
macroMap[PBSBidIDMacro] = prebidGenBidId
}

if len(bid.ADomain) > 0 {
var err error
//macroMap[PBSAdvertiserNameMacro] = strings.Join(bid.ADomain, ",")
macroMap[PBSAdvertiserNameMacro], err = extractDomain(bid.ADomain[0])
if err != nil {
glog.Warningf("Unable to extract domain from '%s'. [%s]", bid.ADomain[0], err.Error())
}
}

if req.App != nil {
// macroMap[VASTAppBundleMacro] = req.App.Bundle
macroMap[VASTDomainMacro] = req.App.Bundle
if req.App.Publisher != nil {
macroMap[PBSAccountMacro] = req.App.Publisher.ID
}
} else if req.Site != nil {
macroMap[VASTDomainMacro] = getDomain(req.Site)
macroMap[VASTPageURLMacro] = req.Site.Page
if req.Site.Publisher != nil {
macroMap[PBSAccountMacro] = req.Site.Publisher.ID
}
}

// lookup in custom macros - keep this block at last for highest priority
var reqExt openrtb_ext.ExtRequest
if req.Ext != nil {
err := json.Unmarshal(req.Ext, &reqExt)
if err != nil {
glog.Warningf("Error in unmarshling req.Ext.Prebid.Vast: [%s]", err.Error())
}
}
for key, value := range reqExt.Prebid.Macros {
macroMap[strings.TrimSpace(key)] = strings.TrimSpace(value)
}

eventURLMap := make(map[string]string)
for name, id := range trackingEventIDMap { // NYC check if trackingEvents and macroMap can be clubbed
// replace [EVENT_ID] macro with PBS defined event ID
macroMap[PBSEventIDMacro] = id
eventURLMap[name] = replaceMacros(trackerURL, macroMap)
}
return eventURLMap
}

func replaceMacros(trackerURL string, macroMap map[string]string) string {
var builder strings.Builder

for i := 0; i < len(trackerURL); i++ {
if trackerURL[i] == '[' {
found := false
j := i + 1
for ; j < len(trackerURL); j++ {
if trackerURL[j] == ']' {
found = true
break
}
}
if found {
n := j + 1
k := trackerURL[i:n]
if v, ok := macroMap[k]; ok {
v = url.QueryEscape(v) // NYC move QueryEscape while creating map, no need to do this everytime
_, _ = builder.Write([]byte(v))
i = j
continue
}
}
}
_ = builder.WriteByte(trackerURL[i])
}

return builder.String()
}

func extractDomain(rawURL string) (string, error) {
if !strings.HasPrefix(rawURL, "http") {
rawURL = "http://" + rawURL
}
// decode rawURL
rawURL, err := url.QueryUnescape(rawURL)
if nil != err {
return "", err
}
url, err := url.Parse(rawURL)
if nil != err {
return "", err
}
// remove www if present
return strings.TrimPrefix(url.Hostname(), "www."), nil
}

func getDomain(site *openrtb2.Site) string {
if site.Domain != "" {
return site.Domain
}

hostname := ""

if site.Page != "" {
pageURL, err := url.Parse(site.Page)
if err == nil && pageURL != nil {
hostname = pageURL.Host
}
}
return hostname
}
Loading

0 comments on commit be2c88b

Please sign in to comment.