@@ -83,12 +83,21 @@ public HttpForwarder(ILogger<HttpForwarder> logger, IClock clock)
8383 /// ASP .NET Core (Kestrel) will finally send response trailers (if any)
8484 /// after we complete the steps above and relinquish control.
8585 /// </remarks>
86- public async ValueTask < ForwarderError > SendAsync (
86+ public ValueTask < ForwarderError > SendAsync (
8787 HttpContext context ,
8888 string destinationPrefix ,
8989 HttpMessageInvoker httpClient ,
9090 ForwarderRequestConfig requestConfig ,
9191 HttpTransformer transformer )
92+ => SendAsync ( context , destinationPrefix , httpClient , requestConfig , transformer , CancellationToken . None ) ;
93+
94+ public async ValueTask < ForwarderError > SendAsync (
95+ HttpContext context ,
96+ string destinationPrefix ,
97+ HttpMessageInvoker httpClient ,
98+ ForwarderRequestConfig requestConfig ,
99+ HttpTransformer transformer ,
100+ CancellationToken cancellationToken )
92101 {
93102 _ = context ?? throw new ArgumentNullException ( nameof ( context ) ) ;
94103 _ = destinationPrefix ?? throw new ArgumentNullException ( nameof ( destinationPrefix ) ) ;
@@ -110,7 +119,7 @@ public async ValueTask<ForwarderError> SendAsync(
110119
111120 ForwarderTelemetry . Log . ForwarderStart ( destinationPrefix ) ;
112121
113- var activityCancellationSource = ActivityCancellationTokenSource . Rent ( requestConfig ? . ActivityTimeout ?? DefaultTimeout , context . RequestAborted ) ;
122+ var activityCancellationSource = ActivityCancellationTokenSource . Rent ( requestConfig ? . ActivityTimeout ?? DefaultTimeout , context . RequestAborted , cancellationToken ) ;
114123 try
115124 {
116125 var isClientHttp2OrGreater = ProtocolHelper . IsHttp2OrGreater ( context . Request . Protocol ) ;
@@ -193,7 +202,7 @@ public async ValueTask<ForwarderError> SendAsync(
193202 {
194203 // :: Step 5: Copy response status line Client ◄-- Proxy ◄-- Destination
195204 // :: Step 6: Copy response headers Client ◄-- Proxy ◄-- Destination
196- var copyBody = await CopyResponseStatusAndHeadersAsync ( destinationResponse , context , transformer ) ;
205+ var copyBody = await CopyResponseStatusAndHeadersAsync ( destinationResponse , context , transformer , activityCancellationSource . Token ) ;
197206
198207 if ( ! copyBody )
199208 {
@@ -260,7 +269,7 @@ public async ValueTask<ForwarderError> SendAsync(
260269 }
261270
262271 // :: Step 8: Copy response trailer headers and finish response Client ◄-- Proxy ◄-- Destination
263- await CopyResponseTrailingHeadersAsync ( destinationResponse , context , transformer ) ;
272+ await CopyResponseTrailingHeadersAsync ( destinationResponse , context , transformer , activityCancellationSource . Token ) ;
264273
265274 if ( isStreamingRequest )
266275 {
@@ -402,14 +411,17 @@ public async ValueTask<ForwarderError> SendAsync(
402411 destinationRequest . Content = requestContent ;
403412
404413 // :: Step 3: Copy request headers Client --► Proxy --► Destination
405- await transformer . TransformRequestAsync ( context , destinationRequest , destinationPrefix ) ;
414+ await transformer . TransformRequestAsync ( context , destinationRequest , destinationPrefix , activityToken . Token ) ;
406415
407416 // The transformer generated a response, do not forward.
408417 if ( RequestUtilities . IsResponseSet ( context . Response ) )
409418 {
410419 return ( destinationRequest , requestContent , false ) ;
411420 }
412421
422+ // Transforms may have taken a while, especially if they buffered the body, they count as forward progress.
423+ activityToken . ResetTimeout ( ) ;
424+
413425 FixupUpgradeRequestHeaders ( context , destinationRequest , outgoingUpgrade , outgoingConnect ) ;
414426
415427 // Allow someone to custom build the request uri, otherwise provide a default for them.
@@ -653,7 +665,7 @@ async ValueTask<ForwarderError> ReportErrorAsync(ForwarderError error, int statu
653665 }
654666 }
655667
656- private static ValueTask < bool > CopyResponseStatusAndHeadersAsync ( HttpResponseMessage source , HttpContext context , HttpTransformer transformer )
668+ private static ValueTask < bool > CopyResponseStatusAndHeadersAsync ( HttpResponseMessage source , HttpContext context , HttpTransformer transformer , CancellationToken cancellationToken )
657669 {
658670 context . Response . StatusCode = ( int ) source . StatusCode ;
659671
@@ -667,7 +679,7 @@ private static ValueTask<bool> CopyResponseStatusAndHeadersAsync(HttpResponseMes
667679 }
668680
669681 // Copies headers
670- return transformer . TransformResponseAsync ( context , source ) ;
682+ return transformer . TransformResponseAsync ( context , source , cancellationToken ) ;
671683 }
672684
673685 private async ValueTask < ForwarderError > HandleUpgradedResponse ( HttpContext context , HttpResponseMessage destinationResponse ,
@@ -891,10 +903,10 @@ private async ValueTask<ForwarderError> HandleResponseBodyErrorAsync(HttpContext
891903 return error ;
892904 }
893905
894- private static ValueTask CopyResponseTrailingHeadersAsync ( HttpResponseMessage source , HttpContext context , HttpTransformer transformer )
906+ private static ValueTask CopyResponseTrailingHeadersAsync ( HttpResponseMessage source , HttpContext context , HttpTransformer transformer , CancellationToken cancellationToken )
895907 {
896908 // Copies trailers
897- return transformer . TransformResponseTrailersAsync ( context , source ) ;
909+ return transformer . TransformResponseTrailersAsync ( context , source , cancellationToken ) ;
898910 }
899911
900912
0 commit comments