11package org .prebid .server .auction .requestfactory ;
22
3+ import com .fasterxml .jackson .databind .JsonNode ;
4+ import com .fasterxml .jackson .databind .node .ArrayNode ;
5+ import com .fasterxml .jackson .databind .node .ObjectNode ;
36import com .iab .openrtb .request .App ;
47import com .iab .openrtb .request .Audio ;
58import com .iab .openrtb .request .Banner ;
1720import io .vertx .core .Future ;
1821import io .vertx .ext .web .RoutingContext ;
1922import lombok .Value ;
23+ import org .apache .commons .collections4 .CollectionUtils ;
24+ import org .apache .commons .lang3 .ObjectUtils ;
2025import org .apache .commons .lang3 .StringUtils ;
2126import org .prebid .server .auction .DebugResolver ;
27+ import org .prebid .server .auction .FpdResolver ;
2228import org .prebid .server .auction .GeoLocationServiceWrapper ;
2329import org .prebid .server .auction .ImplicitParametersExtractor ;
2430import org .prebid .server .auction .InterstitialProcessor ;
2531import org .prebid .server .auction .IpAddressHelper ;
32+ import org .prebid .server .auction .OrtbTypesResolver ;
2633import org .prebid .server .auction .externalortb .ProfilesProcessor ;
2734import org .prebid .server .auction .externalortb .StoredRequestProcessor ;
2835import org .prebid .server .auction .gpp .AuctionGppService ;
2936import org .prebid .server .auction .model .AuctionContext ;
30- import org .prebid .server .auction .model .AuctionStoredResult ;
3137import org .prebid .server .auction .model .ConsentType ;
3238import org .prebid .server .auction .model .IpAddress ;
3339import org .prebid .server .auction .privacy .contextfactory .AuctionPrivacyContextFactory ;
4147import org .prebid .server .model .HttpRequestContext ;
4248import org .prebid .server .proto .openrtb .ext .request .ConsentedProvidersSettings ;
4349import org .prebid .server .proto .openrtb .ext .request .ExtDevice ;
44- import org .prebid .server .proto .openrtb .ext .request .ExtImpPrebid ;
4550import org .prebid .server .proto .openrtb .ext .request .ExtRegs ;
4651import org .prebid .server .proto .openrtb .ext .request .ExtRequest ;
4752import org .prebid .server .proto .openrtb .ext .request .ExtRequestPrebid ;
@@ -69,8 +74,10 @@ public class GetInterfaceRequestFactory {
6974 private final AuctionGppService gppService ;
7075 private final CookieDeprecationService cookieDeprecationService ;
7176 private final ImplicitParametersExtractor paramsExtractor ;
77+ private final OrtbTypesResolver ortbTypesResolver ;
7278 private final IpAddressHelper ipAddressHelper ;
7379 private final Ortb2ImplicitParametersResolver paramsResolver ;
80+ private final FpdResolver fpdResolver ;
7481 private final InterstitialProcessor interstitialProcessor ;
7582 private final AuctionPrivacyContextFactory auctionPrivacyContextFactory ;
7683 private final DebugResolver debugResolver ;
@@ -85,8 +92,10 @@ public GetInterfaceRequestFactory(Ortb2RequestFactory ortb2RequestFactory,
8592 AuctionGppService gppService ,
8693 CookieDeprecationService cookieDeprecationService ,
8794 ImplicitParametersExtractor paramsExtractor ,
95+ OrtbTypesResolver ortbTypesResolver ,
8896 IpAddressHelper ipAddressHelper ,
8997 Ortb2ImplicitParametersResolver paramsResolver ,
98+ FpdResolver fpdResolver ,
9099 InterstitialProcessor interstitialProcessor ,
91100 AuctionPrivacyContextFactory auctionPrivacyContextFactory ,
92101 DebugResolver debugResolver ,
@@ -101,8 +110,10 @@ public GetInterfaceRequestFactory(Ortb2RequestFactory ortb2RequestFactory,
101110 this .gppService = Objects .requireNonNull (gppService );
102111 this .cookieDeprecationService = Objects .requireNonNull (cookieDeprecationService );
103112 this .paramsExtractor = Objects .requireNonNull (paramsExtractor );
113+ this .ortbTypesResolver = Objects .requireNonNull (ortbTypesResolver );
104114 this .ipAddressHelper = Objects .requireNonNull (ipAddressHelper );
105115 this .paramsResolver = Objects .requireNonNull (paramsResolver );
116+ this .fpdResolver = Objects .requireNonNull (fpdResolver );
106117 this .interstitialProcessor = Objects .requireNonNull (interstitialProcessor );
107118 this .auctionPrivacyContextFactory = Objects .requireNonNull (auctionPrivacyContextFactory );
108119 this .debugResolver = Objects .requireNonNull (debugResolver );
@@ -125,37 +136,35 @@ public Future<AuctionContext> fromRequest(RoutingContext routingContext, long st
125136 initialBidRequest (httpRequest ),
126137 startTime ))
127138
139+ .recover (ortb2RequestFactory ::restoreResultFromRejection );
140+ }
141+
142+ public Future <AuctionContext > enrichAuctionContext (AuctionContext initialContext ) {
143+ if (initialContext .isRequestRejected ()) {
144+ return Future .succeededFuture (initialContext );
145+ }
146+
147+ return Future .succeededFuture (addTmpPublisher (initialContext ))
148+
128149 .compose (auctionContext -> ortb2RequestFactory .fetchAccount (auctionContext )
129150 .map (auctionContext ::with ))
130151
131152 .map (auctionContext -> auctionContext .with (removeTmpPublisher (auctionContext .getBidRequest ())))
132153
133154 .map (auctionContext -> auctionContext .with (debugResolver .debugContextFrom (auctionContext )))
134155
135- .compose (auctionContext -> storedRequestProcessor .processAuctionRequest (
136- auctionContext .getAccount ().getId (), auctionContext .getBidRequest ())
137- .map (AuctionStoredResult ::bidRequest )
156+ .compose (auctionContext -> storedRequestProcessor .processAmpRequest (
157+ auctionContext .getAccount ().getId (),
158+ storedRequestId (auctionContext .getBidRequest ()),
159+ auctionContext .getBidRequest ())
138160 .map (auctionContext ::with ))
139161
140- .compose (auctionContext -> profilesProcessor .process (auctionContext , auctionContext .getBidRequest ())
141- .map (auctionContext ::with ))
142-
143- .map (auctionContext -> auctionContext .with (completeBidRequest (
144- auctionContext .getBidRequest (),
145- auctionContext .getHttpRequest (),
146- auctionContext .getAccount ())))
162+ .map (auctionContext -> auctionContext .with (completeBidRequest (auctionContext )))
147163
148164 .map (auctionContext -> auctionContext .with (requestTypeMetric (auctionContext .getBidRequest ())))
149165
150- .recover (ortb2RequestFactory ::restoreResultFromRejection );
151- }
152-
153- public Future <AuctionContext > enrichAuctionContext (AuctionContext initialContext ) {
154- if (initialContext .isRequestRejected ()) {
155- return Future .succeededFuture (initialContext );
156- }
157-
158- return Future .succeededFuture (initialContext )
166+ .compose (auctionContext -> profilesProcessor .process (auctionContext , auctionContext .getBidRequest ())
167+ .map (auctionContext ::with ))
159168
160169 .compose (auctionContext -> geoLocationServiceWrapper .lookup (auctionContext )
161170 .map (auctionContext ::with ))
@@ -193,8 +202,6 @@ private BidRequest initialBidRequest(HttpRequestContext httpRequest) {
193202 final Consent consent = params .consent ();
194203
195204 return BidRequest .builder ()
196- .imp (Collections .singletonList (initialImp (params )))
197- .site (tmpSite (params )) // Temporarily add to fetch account
198205 .device (initialDevice (params ))
199206 .user (initialUser (params , consent ))
200207 .tmax (params .tmax ())
@@ -205,21 +212,6 @@ private BidRequest initialBidRequest(HttpRequestContext httpRequest) {
205212 .build ();
206213 }
207214
208- private Imp initialImp (GetInterfaceParams params ) {
209- return Imp .builder ()
210- .tagid (params .tagId ())
211- .ext (mapper .mapper ().valueToTree (ExtImpPrebid .builder ()
212- .profiles (params .impProfiles ())
213- .build ()))
214- .build ();
215- }
216-
217- private static Site tmpSite (GetInterfaceParams params ) {
218- return Site .builder ()
219- .publisher (Publisher .builder ().id (params .accountId ()).build ())
220- .build ();
221- }
222-
223215 private static Device initialDevice (GetInterfaceParams params ) {
224216 final IpAddress ipAddress = params .ip ();
225217 return Device .builder ()
@@ -259,37 +251,93 @@ private static ExtRequest initialExtRequest(GetInterfaceParams params) {
259251 .debug (params .debug ())
260252 .storedrequest (ExtStoredRequest .of (params .storedRequestId ()))
261253 .profiles (params .requestProfiles ())
262- .storedAuctionResponse (ExtStoredAuctionResponse .of (
263- params .storedAuctionResponseId (), null , null ))
254+ .storedAuctionResponse (ExtStoredAuctionResponse .of (params .storedAuctionResponseId (), null , null ))
264255 .outputFormat (params .outputFormat ())
265256 .outputModule (params .outputModule ())
266257 .build ());
267258 }
268259
260+ private AuctionContext addTmpPublisher (AuctionContext auctionContext ) {
261+ final GetInterfaceParams params = new GetInterfaceParams (auctionContext .getHttpRequest ());
262+ final BidRequest bidRequestWithTmpPublisher = auctionContext .getBidRequest ().toBuilder ()
263+ .site (Site .builder ()
264+ .publisher (Publisher .builder ().id (params .accountId ()).build ())
265+ .build ())
266+ .build ();
267+
268+ return auctionContext .with (bidRequestWithTmpPublisher );
269+ }
270+
269271 private static BidRequest removeTmpPublisher (BidRequest bidRequest ) {
270272 return bidRequest .toBuilder ().site (null ).build ();
271273 }
272274
273- private BidRequest completeBidRequest (BidRequest bidRequest ,
274- HttpRequestContext httpRequest ,
275- Account account ) {
275+ private static String storedRequestId (BidRequest bidRequest ) {
276+ return bidRequest . getExt (). getPrebid (). getStoredrequest (). getId ();
277+ }
276278
277- final GetInterfaceParams params = new GetInterfaceParams (httpRequest );
279+ private BidRequest completeBidRequest (AuctionContext auctionContext ) {
280+ final Account account = auctionContext .getAccount ();
281+ final GetInterfaceParams params = new GetInterfaceParams (auctionContext .getHttpRequest ());
278282
279- final Imp imp = bidRequest .getImp ().getFirst ();
283+ final BidRequest bidRequest = auctionContext .getBidRequest ();
284+ final Imp imp = Optional .ofNullable (bidRequest .getImp ())
285+ .filter (CollectionUtils ::isNotEmpty )
286+ .map (List ::getFirst )
287+ .orElse (null );
280288
281289 return bidRequest .toBuilder ()
282- .imp (Collections .singletonList (imp .toBuilder ()
283- .banner (completeBanner (imp .getBanner (), params ))
284- .video (completeVideo (imp .getVideo (), params ))
285- .audio (completeAudio (imp .getAudio (), params ))
286- .build ()))
290+ .imp (Collections .singletonList (completeImp (imp , params )))
287291 .site (completeSite (bidRequest .getSite (), params , account ))
288292 .app (completeApp (bidRequest .getApp (), params , account ))
289293 .dooh (completeDooh (bidRequest .getDooh (), params , account ))
290294 .build ();
291295 }
292296
297+ private Imp completeImp (Imp imp , GetInterfaceParams params ) {
298+ if (imp == null ) {
299+ return null ;
300+ }
301+
302+ return imp .toBuilder ()
303+ .banner (completeBanner (imp .getBanner (), params ))
304+ .video (completeVideo (imp .getVideo (), params ))
305+ .audio (completeAudio (imp .getAudio (), params ))
306+ .tagid (ObjectUtils .defaultIfNull (params .tagId (), imp .getTagid ()))
307+ .ext (completeImpExt (imp .getExt (), params ))
308+ .build ();
309+ }
310+
311+ private ObjectNode completeImpExt (ObjectNode ext , GetInterfaceParams params ) {
312+ final ObjectNode extWithTargeting = enrichImpExtWithTargeting (ext , params );
313+ return enrichImpExtWithProfiles (extWithTargeting , params );
314+ }
315+
316+ private ObjectNode enrichImpExtWithTargeting (ObjectNode ext , GetInterfaceParams params ) {
317+ final ObjectNode targetingNode = params .targeting ();
318+
319+ return targetingNode != null
320+ ? fpdResolver .resolveImpExt (ext , targetingNode )
321+ : ext ;
322+ }
323+
324+ private ObjectNode enrichImpExtWithProfiles (ObjectNode ext , GetInterfaceParams params ) {
325+ final List <String > impProfiles = params .impProfiles ();
326+ if (CollectionUtils .isEmpty (impProfiles )) {
327+ return ext ;
328+ }
329+
330+ final ObjectNode modifiedExt = ext != null ? ext : mapper .mapper ().createObjectNode ();
331+ final ObjectNode extPrebid = Optional .ofNullable (modifiedExt .get ("prebid" ))
332+ .filter (JsonNode ::isObject )
333+ .map (ObjectNode .class ::cast )
334+ .orElseGet (() -> modifiedExt .putObject ("prebid" ));
335+ final ArrayNode profiles = extPrebid .putArray ("profiles" );
336+ impProfiles .forEach (profiles ::add );
337+
338+ return modifiedExt ;
339+ }
340+
293341 private static Banner completeBanner (Banner banner , GetInterfaceParams params ) {
294342 if (banner == null ) {
295343 return null ;
@@ -476,13 +524,16 @@ private class GetInterfaceParams {
476524
477525 HttpRequestContext httpRequestContext ;
478526
527+ List <String > errors = new ArrayList <>();
528+
479529 GetInterfaceParams (HttpRequestContext httpRequestContext ) {
480530 this .httpRequestContext = Objects .requireNonNull (httpRequestContext );
481531 }
482532
483533 public String storedRequestId () {
484534 return Optional .ofNullable (getString ("srid" ))
485- .orElseGet (() -> getString ("tag_id" ));
535+ .or (() -> Optional .ofNullable (getString ("tag_id" )))
536+ .orElseThrow (() -> new InvalidRequestException ("Request require the stored request id." ));
486537 }
487538
488539 public String accountId () {
@@ -707,8 +758,12 @@ public Integer topFrame() {
707758 return getInteger ("topframe" );
708759 }
709760
710- public Integer targeting () {
711- return null ; // TODO: GET
761+ public ObjectNode targeting () {
762+ final ObjectNode targetingNode = AmpRequestFactory .readTargeting (getString ("targeting" ), mapper );
763+ final String referer = paramsExtractor .refererFrom (httpRequestContext );
764+ ortbTypesResolver .normalizeTargeting (targetingNode , errors , referer );
765+
766+ return targetingNode ;
712767 }
713768
714769 public Consent consent () {
@@ -846,7 +901,7 @@ public Integer liveStream() {
846901 public IpAddress ip () {
847902 return Optional .ofNullable (getString ("ip" ))
848903 .map (ipAddressHelper ::toIpAddress )
849- .orElse (null );
904+ .orElse (IpAddress . of ( null , null ) );
850905 }
851906
852907 public String ua () {
0 commit comments