@@ -114,11 +114,7 @@ public void StopRecording(string sessionId, IDictionary<string, string> variable
114114 }
115115
116116 var sanitizers = SanitizerRegistry . GetSanitizers ( recordingSession ) ;
117-
118- foreach ( RecordedTestSanitizer sanitizer in sanitizers )
119- {
120- recordingSession . Session . Sanitize ( sanitizer ) ;
121- }
117+ recordingSession . Session . Sanitize ( sanitizers ) ;
122118
123119 if ( variables != null )
124120 {
@@ -457,16 +453,15 @@ public async Task HandlePlaybackRequest(string recordingId, HttpRequest incoming
457453
458454 var sanitizers = SanitizerRegistry . GetSanitizers ( session ) ;
459455
460- // we don't need to re-sanitize with recording-applicable sanitizers every time. just the very first one
461- lock ( session )
456+ if ( ! session . IsSanitized )
462457 {
463- if ( ! session . IsSanitized )
458+ // we don't need to re-sanitize with recording-applicable sanitizers every time. just the very first one
459+ lock ( session . SanitizerLock )
464460 {
465- session . IsSanitized = true ;
466-
467- foreach ( RecordedTestSanitizer sanitizer in sanitizers )
461+ if ( ! session . IsSanitized )
468462 {
469- session . Session . Sanitize ( sanitizer ) ;
463+ session . Session . Sanitize ( sanitizers ) ;
464+ session . IsSanitized = true ;
470465 }
471466 }
472467 }
@@ -475,23 +470,14 @@ public async Task HandlePlaybackRequest(string recordingId, HttpRequest incoming
475470
476471 var entry = ( await CreateEntryAsync ( incomingRequest ) . ConfigureAwait ( false ) ) . Item1 ;
477472
478- // If request contains "x-recording-remove: false", then request is not removed from session after playback.
479- // Used by perf tests to play back the same request multiple times.
480- var remove = true ;
481- if ( incomingRequest . Headers . TryGetValue ( "x-recording-remove" , out var removeHeader ) )
482- {
483- remove = bool . Parse ( removeHeader ) ;
484- }
485-
486- var match = session . Session . Lookup ( entry , session . CustomMatcher ?? Matcher , sanitizers , remove ) ;
473+ // Session may be removed later, but only after response has been fully written
474+ var match = session . Session . Lookup ( entry , session . CustomMatcher ?? Matcher , sanitizers , remove : false ) ;
487475
488476 foreach ( ResponseTransform transform in Transforms . Concat ( session . AdditionalTransforms ) )
489477 {
490478 transform . Transform ( incomingRequest , match ) ;
491479 }
492480
493- Interlocked . Increment ( ref Startup . RequestsPlayedBack ) ;
494-
495481 outgoingResponse . StatusCode = match . StatusCode ;
496482
497483 foreach ( var header in match . Response . Headers )
@@ -512,6 +498,23 @@ public async Task HandlePlaybackRequest(string recordingId, HttpRequest incoming
512498
513499 await WriteBodyBytes ( bodyData , session . PlaybackResponseTime , outgoingResponse ) ;
514500 }
501+
502+ Interlocked . Increment ( ref Startup . RequestsPlayedBack ) ;
503+
504+ // Only remove session once body has been written, to minimize probability client retries but test-proxy has already removed the session
505+ var remove = true ;
506+
507+ // If request contains "x-recording-remove: false", then request is not removed from session after playback.
508+ // Used by perf tests to play back the same request multiple times.
509+ if ( incomingRequest . Headers . TryGetValue ( "x-recording-remove" , out var removeHeader ) )
510+ {
511+ remove = bool . Parse ( removeHeader ) ;
512+ }
513+
514+ if ( remove )
515+ {
516+ session . Session . Remove ( match ) ;
517+ }
515518 }
516519
517520 public byte [ ] [ ] GetBatches ( byte [ ] bodyData , int batchCount )
0 commit comments