@@ -135,6 +135,8 @@ public void init() {
135
135
subscriptionService .registerCallback (EVENTS .requestMethodUriRaw (), this ::onRequestMethodUriRaw );
136
136
subscriptionService .registerCallback (EVENTS .requestBodyStart (), this ::onRequestBodyStart );
137
137
subscriptionService .registerCallback (EVENTS .requestBodyDone (), this ::onRequestBodyDone );
138
+ subscriptionService .registerCallback (EVENTS .responseBodyStart (), this ::onResponseBodyStart );
139
+ subscriptionService .registerCallback (EVENTS .responseBodyDone (), this ::onResponseBodyDone );
138
140
subscriptionService .registerCallback (
139
141
EVENTS .requestClientSocketAddress (), this ::onRequestClientSocketAddress );
140
142
subscriptionService .registerCallback (
@@ -164,6 +166,10 @@ public void init() {
164
166
subscriptionService .registerCallback (
165
167
EVENTS .requestBodyProcessed (), this ::onRequestBodyProcessed );
166
168
}
169
+ if (additionalIGEvents .contains (EVENTS .responseBodyProcessed ())) {
170
+ subscriptionService .registerCallback (
171
+ EVENTS .responseBodyProcessed (), this ::onResponseBodyProcessed );
172
+ }
167
173
}
168
174
169
175
/**
@@ -596,6 +602,51 @@ private Flow<Void> onRequestBodyProcessed(RequestContext ctx_, Object obj) {
596
602
}
597
603
}
598
604
605
+ private Flow <Void > onResponseBodyProcessed (RequestContext ctx_ , Object obj ) {
606
+ AppSecRequestContext ctx = ctx_ .getData (RequestContextSlot .APPSEC );
607
+ if (ctx == null ) {
608
+ return NoopFlow .INSTANCE ;
609
+ }
610
+
611
+ if (ctx .isConvertedResBodyPublished ()) {
612
+ log .debug (
613
+ "Response body already published; will ignore new value of type {}" , obj .getClass ());
614
+ return NoopFlow .INSTANCE ;
615
+ }
616
+ ctx .setConvertedResBodyPublished (true );
617
+
618
+ while (true ) {
619
+ DataSubscriberInfo subInfo = responseBodySubInfo ;
620
+ if (subInfo == null ) {
621
+ subInfo = producerService .getDataSubscribers (KnownAddresses .RESPONSE_BODY_OBJECT );
622
+ responseBodySubInfo = subInfo ;
623
+ }
624
+ if (subInfo == null || subInfo .isEmpty ()) {
625
+ return NoopFlow .INSTANCE ;
626
+ }
627
+ Object converted =
628
+ ObjectIntrospection .convert (
629
+ obj ,
630
+ ctx ,
631
+ () -> {
632
+ if (Config .get ().isAppSecRaspCollectRequestBody ()) {
633
+ ctx_ .getTraceSegment ()
634
+ .setTagTop ("_dd.appsec.rasp.response_body_size.exceeded" , true );
635
+ }
636
+ });
637
+ if (Config .get ().isAppSecRaspCollectResponseBody ()) {
638
+ ctx .setProcessedResponseBody (converted );
639
+ }
640
+ DataBundle bundle = new SingletonDataBundle <>(KnownAddresses .RESPONSE_BODY_OBJECT , converted );
641
+ try {
642
+ GatewayContext gwCtx = new GatewayContext (false );
643
+ return producerService .publishDataEvent (subInfo , ctx , bundle , gwCtx );
644
+ } catch (ExpiredSubscriberInfoException e ) {
645
+ responseBodySubInfo = null ;
646
+ }
647
+ }
648
+ }
649
+
599
650
private Flow <Void > onRequestBodyDone (RequestContext ctx_ , StoredBodySupplier supplier ) {
600
651
AppSecRequestContext ctx = ctx_ .getData (RequestContextSlot .APPSEC );
601
652
if (ctx == null || ctx .isRawReqBodyPublished ()) {
@@ -627,6 +678,37 @@ private Flow<Void> onRequestBodyDone(RequestContext ctx_, StoredBodySupplier sup
627
678
}
628
679
}
629
680
681
+ private Flow <Void > onResponseBodyDone (RequestContext ctx_ , StoredBodySupplier supplier ) {
682
+ AppSecRequestContext ctx = ctx_ .getData (RequestContextSlot .APPSEC );
683
+ if (ctx == null || ctx .isRawResBodyPublished ()) {
684
+ return NoopFlow .INSTANCE ;
685
+ }
686
+ ctx .setRawResBodyPublished (true );
687
+
688
+ while (true ) {
689
+ DataSubscriberInfo subInfo = rawResponseBodySubInfo ;
690
+ if (subInfo == null ) {
691
+ subInfo = producerService .getDataSubscribers (KnownAddresses .RESPONSE_BODY_RAW );
692
+ rawResponseBodySubInfo = subInfo ;
693
+ }
694
+ if (subInfo == null || subInfo .isEmpty ()) {
695
+ return NoopFlow .INSTANCE ;
696
+ }
697
+
698
+ CharSequence bodyContent = supplier .get ();
699
+ if (bodyContent == null || bodyContent .length () == 0 ) {
700
+ return NoopFlow .INSTANCE ;
701
+ }
702
+ DataBundle bundle = new SingletonDataBundle <>(KnownAddresses .RESPONSE_BODY_RAW , bodyContent );
703
+ try {
704
+ GatewayContext gwCtx = new GatewayContext (false );
705
+ return producerService .publishDataEvent (subInfo , ctx , bundle , gwCtx );
706
+ } catch (ExpiredSubscriberInfoException e ) {
707
+ rawResponseBodySubInfo = null ;
708
+ }
709
+ }
710
+ }
711
+
630
712
private Flow <Void > onRequestPathParams (RequestContext ctx_ , Map <String , ?> data ) {
631
713
AppSecRequestContext ctx = ctx_ .getData (RequestContextSlot .APPSEC );
632
714
if (ctx == null || ctx .isPathParamsPublished ()) {
@@ -663,6 +745,16 @@ private Void onRequestBodyStart(RequestContext ctx_, StoredBodySupplier supplier
663
745
return null ;
664
746
}
665
747
748
+ private Void onResponseBodyStart (RequestContext ctx_ , StoredBodySupplier supplier ) {
749
+ AppSecRequestContext ctx = ctx_ .getData (RequestContextSlot .APPSEC );
750
+ if (ctx == null ) {
751
+ return null ;
752
+ }
753
+
754
+ ctx .setStoredResponseBodySupplier (supplier );
755
+ return null ;
756
+ }
757
+
666
758
private Flow <AppSecRequestContext > onRequestStarted () {
667
759
if (!AppSecSystem .isActive ()) {
668
760
return RequestContextSupplier .EMPTY ;
0 commit comments