2626import com .datadog .appsec .report .AppSecEvent ;
2727import com .datadog .appsec .report .AppSecEventWrapper ;
2828import com .datadog .appsec .util .BodyParser ;
29+ import datadog .appsec .api .blocking .BlockingContentType ;
2930import datadog .trace .api .Config ;
3031import datadog .trace .api .ProductTraceSource ;
3132import datadog .trace .api .appsec .HttpClientPayload ;
4243import datadog .trace .api .telemetry .LoginEvent ;
4344import datadog .trace .api .telemetry .RuleType ;
4445import datadog .trace .api .telemetry .WafMetricCollector ;
46+ import datadog .trace .bootstrap .blocking .BlockingActionHelper ;
4547import datadog .trace .bootstrap .instrumentation .api .Tags ;
4648import datadog .trace .bootstrap .instrumentation .api .URIDataAdapter ;
4749import datadog .trace .util .stacktrace .StackTraceEvent ;
@@ -929,6 +931,18 @@ private NoopFlow onRequestEnded(RequestContext ctx_, IGSpanInfo spanInfo) {
929931 writeResponseHeaders (
930932 ctx , traceSeg , RESPONSE_HEADERS_ALLOW_LIST , ctx .getResponseHeaders (), false );
931933 }
934+ // For blocking responses the normal response-header collection is bypassed; write the
935+ // content-type and content-length that were determined when the blocking action was raised.
936+ String blockingContentType = ctx .getBlockingResponseContentType ();
937+ if (blockingContentType != null ) {
938+ traceSeg .setTagTop ("http.response.headers.content-type" , blockingContentType );
939+ Integer blockingContentLength = ctx .getBlockingResponseContentLength ();
940+ if (blockingContentLength != null ) {
941+ traceSeg .setTagTop (
942+ "http.response.headers.content-length" , String .valueOf (blockingContentLength ));
943+ }
944+ }
945+
932946 // If extracted any derivatives - commit them
933947 if (!ctx .commitDerivatives (traceSeg )) {
934948 log .debug ("Unable to commit, derivatives will be skipped {}" , ctx .getDerivativeKeys ());
@@ -1230,7 +1244,9 @@ private Flow<Void> maybePublishRequestData(AppSecRequestContext ctx) {
12301244
12311245 try {
12321246 GatewayContext gwCtx = new GatewayContext (false );
1233- return producerService .publishDataEvent (subInfo , ctx , bundle , gwCtx );
1247+ Flow <Void > flow = producerService .publishDataEvent (subInfo , ctx , bundle , gwCtx );
1248+ maybeRecordBlockingContentType (ctx , flow );
1249+ return flow ;
12341250 } catch (ExpiredSubscriberInfoException e ) {
12351251 this .initialReqDataSubInfo = null ;
12361252 }
@@ -1263,7 +1279,9 @@ private Flow<Void> maybePublishResponseData(AppSecRequestContext ctx) {
12631279
12641280 try {
12651281 GatewayContext gwCtx = new GatewayContext (false );
1266- return producerService .publishDataEvent (subInfo , ctx , bundle , gwCtx );
1282+ Flow <Void > flow = producerService .publishDataEvent (subInfo , ctx , bundle , gwCtx );
1283+ maybeRecordBlockingContentType (ctx , flow );
1284+ return flow ;
12671285 } catch (ExpiredSubscriberInfoException e ) {
12681286 respDataSubInfo = null ;
12691287 }
@@ -1277,6 +1295,26 @@ private ApiSecurityDownstreamSampler downstreamSampler() {
12771295 return downstreamSampler ;
12781296 }
12791297
1298+ private static void maybeRecordBlockingContentType (AppSecRequestContext ctx , Flow <?> flow ) {
1299+ Flow .Action action = flow .getAction ();
1300+ if (!(action instanceof Flow .Action .RequestBlockingAction )) {
1301+ return ;
1302+ }
1303+ Flow .Action .RequestBlockingAction rba = (Flow .Action .RequestBlockingAction ) action ;
1304+ BlockingContentType bct = rba .getBlockingContentType ();
1305+ if (bct == BlockingContentType .NONE ) {
1306+ return ; // redirect — no response body
1307+ }
1308+ List <String > acceptValues = ctx .getRequestHeaders ().get ("accept" );
1309+ String acceptHeader =
1310+ (acceptValues == null || acceptValues .isEmpty ()) ? null : acceptValues .get (0 );
1311+ BlockingActionHelper .TemplateType tt =
1312+ BlockingActionHelper .determineTemplateType (bct , acceptHeader );
1313+ byte [] template = BlockingActionHelper .getTemplate (tt , rba .getSecurityResponseId ());
1314+ ctx .setBlockingResponseContentType (BlockingActionHelper .getContentType (tt ));
1315+ ctx .setBlockingResponseContentLength (template .length );
1316+ }
1317+
12801318 private static Map <String , List <String >> parseQueryStringParams (
12811319 String queryString , Charset uriEncoding ) {
12821320 if (queryString == null ) {
0 commit comments