Skip to content
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

OTT-1564: [bug fix] avoid database calls in vast-unwrap module for hybrid+activation endpoint #719

Merged
merged 2 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions modules/pubmatic/vastunwrap/entryhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@ package vastunwrap

import (
"context"
"fmt"
"math/rand"
"runtime/debug"

"github.com/golang/glog"
"github.com/prebid/prebid-server/hooks/hookstage"
"github.com/prebid/prebid-server/modules/pubmatic/openwrap"
ow_models "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models"
)

var getRandomNumber = func() int {
return rand.Intn(100)
}

// supportedEndpoints holds the list of endpoints which supports VAST-unwrap feature
var supportedEndpoints = map[string]struct{}{
ow_models.EndpointVAST: {},
ow_models.EndpointVideo: {},
ow_models.EndpointJson: {},
ow_models.EndpointV25: {},
}

func getVastUnwrapperEnable(ctx context.Context, field string) bool {
vastEnableUnwrapper, _ := ctx.Value(field).(string)
return vastEnableUnwrapper == "1"
Expand All @@ -29,7 +39,9 @@ func handleEntrypointHook(
glog.Errorf("body:[%s] Error:[%v] stacktrace:[%s]", string(payload.Body), r, string(debug.Stack()))
}
}()
result := hookstage.HookResult[hookstage.EntrypointPayload]{}
result := hookstage.HookResult[hookstage.EntrypointPayload]{
ModuleContext: make(hookstage.ModuleContext),
}
vastRequestContext := models.RequestCtx{}
queryParams := payload.Request.URL.Query()
source := queryParams.Get("source")
Expand All @@ -40,14 +52,17 @@ func handleEntrypointHook(
}
} else {
endpoint := openwrap.GetEndpoint(payload.Request.URL.Path, source)
if _, ok := supportedEndpoints[endpoint]; !ok {
result.DebugMessages = append(result.DebugMessages, fmt.Sprintf("%s endpoint does not support vast-unwrap feature", endpoint))
return result, nil
}
requestExtWrapper, _ := openwrap.GetRequestWrapper(payload, result, endpoint)
vastRequestContext = models.RequestCtx{
ProfileID: requestExtWrapper.ProfileId,
DisplayID: requestExtWrapper.VersionId,
Endpoint: endpoint,
}
}
result.ModuleContext = make(hookstage.ModuleContext)
result.ModuleContext[RequestContext] = vastRequestContext
return result, nil
}
116 changes: 85 additions & 31 deletions modules/pubmatic/vastunwrap/entryhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,25 @@ package vastunwrap
import (
"context"
"net/http"
"reflect"
"testing"

"github.com/prebid/prebid-server/hooks/hookstage"
ow_models "github.com/prebid/prebid-server/modules/pubmatic/openwrap/models"
"github.com/prebid/prebid-server/modules/pubmatic/vastunwrap/models"
"github.com/stretchr/testify/assert"
)

func TestHandleEntrypointHook(t *testing.T) {
type args struct {
payload hookstage.EntrypointPayload
config VastUnwrapModule
}
tests := []struct {
name string
args args
randomNum int
want hookstage.HookResult[hookstage.EntrypointPayload]
name string
args args
want hookstage.HookResult[hookstage.EntrypointPayload]
}{
{
name: "Disable Vast Unwrapper",
name: "Disable Vast Unwrapper for CTV video/openrtb request",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
Expand All @@ -35,15 +34,11 @@ func TestHandleEntrypointHook(t *testing.T) {
return r
}(),
},
config: VastUnwrapModule{
TrafficPercentage: 2,
Enabled: false,
},
},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: true}}},
},
{
name: "Enable Vast Unwrapper",
name: "Enable Vast Unwrapper for CTV video/openrtb request",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
Expand All @@ -56,54 +51,113 @@ func TestHandleEntrypointHook(t *testing.T) {
return r
}(),
},
config: VastUnwrapModule{
TrafficPercentage: 2,
},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
},
{
name: "Vast Unwrapper for IN-APP openrtb2/auction request",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
r, _ := http.NewRequest("POST", "http://localhost/openrtb2/auction?source=owsdk", nil)
return r
}(),
Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
},
},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: false, ProfileID: 5890, DisplayID: 1, Endpoint: ow_models.EndpointV25}}},
},
{
name: "Vast Unwrapper for IN-APP /openrtb/2.5 request coming from SSHB",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/openrtb2/auction?sshb=1", nil)
return r
}(),
Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
},
},
randomNum: 1,
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true}}},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: true, Redirect: true, ProfileID: 0, DisplayID: 0, Endpoint: ""}}},
},
{
name: "Disable Vast Unwrapper for owsdk source request",
name: "Vast Unwrapper for IN-APP /openrtb/2.5 request directly coming to prebid",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
r, _ := http.NewRequest("POST", "http://localhost/video/openrtb?source=owsdk", nil)
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/openrtb/2.5", nil)
return r
}(),
Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
},
config: VastUnwrapModule{
TrafficPercentage: 2,
Enabled: false,
},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: false, ProfileID: 5890, DisplayID: 1, Endpoint: ow_models.EndpointV25}}},
},
{
name: "Vast Unwrapper for WebS2S activation request",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost/openrtb2/auction?source=pbjs", nil)
return r
}(),
Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
},
},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: false, ProfileID: 5890, DisplayID: 1, Endpoint: "video"}}},
want: hookstage.HookResult[hookstage.EntrypointPayload]{
ModuleContext: hookstage.ModuleContext{},
DebugMessages: []string{"webs2s endpoint does not support vast-unwrap feature"},
},
},
{
name: "Enable Vast Unwrapper for owsdk source request",
name: "Vast Unwrapper for Hybrid request",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
r, _ := http.NewRequest("POST", "http://localhost/video/openrtb?source=owsdk", nil)
ctx := context.WithValue(context.Background(), VastUnwrapEnabled, "1")
r, _ := http.NewRequestWithContext(ctx, "POST", "http://localhost:8001/pbs/openrtb2/auction", nil)
return r
}(),
Body: []byte(`{"ext":{"wrapper":{"profileid":5890,"versionid":1}}}`),
},
config: VastUnwrapModule{
TrafficPercentage: 2,
},
want: hookstage.HookResult[hookstage.EntrypointPayload]{
ModuleContext: hookstage.ModuleContext{},
DebugMessages: []string{"hybrid endpoint does not support vast-unwrap feature"},
},
},
{
name: "Vast Unwrapper for AMP request coming from SSHB",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
r, _ := http.NewRequest("GET", "http://localhost:8001/amp?sshb=1&v=1&w=300&h=250", nil)
return r
}(),
},
},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: true, Endpoint: ""}}},
},
{
name: "Vast Unwrapper for IN-APP OTT request coming from SSHB",
args: args{
payload: hookstage.EntrypointPayload{
Request: func() *http.Request {
r, _ := http.NewRequest("GET", "http://localhost:8001/openrtb/2.5/video?sshb=1&owLoggerDebug=1&pubId=5890&profId=2543", nil)
return r
}(),
},
},
randomNum: 1,
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: false, ProfileID: 5890, DisplayID: 1, Endpoint: "video"}}},
want: hookstage.HookResult[hookstage.EntrypointPayload]{ModuleContext: hookstage.ModuleContext{"rctx": models.RequestCtx{VastUnwrapEnabled: false, Redirect: true, Endpoint: ""}}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, _ := handleEntrypointHook(nil, hookstage.ModuleInvocationContext{}, tt.args.payload)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("handleEntrypointHook() = %#v, want %#v", got, tt.want)
}
assert.Equal(t, tt.want, got, "mismatched handleEntrypointHook output")
})
}
}
8 changes: 6 additions & 2 deletions modules/pubmatic/vastunwrap/hook_raw_bidder_response.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package vastunwrap

import (
"fmt"
"strconv"
"sync"

Expand All @@ -24,14 +25,17 @@ func (m VastUnwrapModule) handleRawBidderResponseHook(
if !vastRequestContext.Redirect {
pubId, _ := strconv.Atoi(miCtx.AccountID)
vastRequestContext.PubID = pubId
vastUnwrapEnabled = m.getVastUnwrapEnable(vastRequestContext) && getRandomNumber() < m.TrafficPercentage
vastUnwrapEnabled = getRandomNumber() < m.TrafficPercentage && m.getVastUnwrapEnable(vastRequestContext)
result.DebugMessages = append(result.DebugMessages,
fmt.Sprintf("found request without sshb=1 in handleRawBidderResponseHook() for pubid:[%d]", vastRequestContext.PubID))
}

vastRequestContext.VastUnwrapEnabled = vastUnwrapEnabled
vastRequestContext.VastUnwrapStatsEnabled = getRandomNumber() < m.StatTrafficPercentage

if !vastRequestContext.VastUnwrapEnabled && !vastRequestContext.VastUnwrapStatsEnabled {
result.DebugMessages = append(result.DebugMessages, "error: vast unwrap flag is not enabled in handleRawBidderResponseHook()")
result.DebugMessages = append(result.DebugMessages,
fmt.Sprintf("error: vast unwrap flag is not enabled in handleRawBidderResponseHook() for pubid:[%d]", vastRequestContext.PubID))
return result, nil
}

Expand Down
12 changes: 6 additions & 6 deletions modules/pubmatic/vastunwrap/models/request.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package models

type RequestCtx struct {
UA string
VastUnwrapEnabled bool
PubID, ProfileID, DisplayID, VersionID int
Endpoint string
VastUnwrapStatsEnabled bool
Redirect bool
UA string
VastUnwrapEnabled bool
PubID, ProfileID, DisplayID int
Endpoint string
VastUnwrapStatsEnabled bool
Redirect bool
}
Loading