@@ -198,47 +198,49 @@ private LimitedLocalhostHttpServer(TcpListener listener)
198198 private async Task < Dictionary < string , string > > GetQueryParamsFromClientAsync ( TcpClient client , CancellationToken cancellationToken )
199199 {
200200 var stream = client . GetStream ( ) ;
201-
202- var buffer = new byte [ NetworkReadBufferSize ] ;
203- int bufferOfs = 0 ;
204- int bufferSize = 0 ;
205- Func < Task < char ? > > getChar = async ( ) =>
201+ // NetworkStream.ReadAsync() doesn't honour the cancellation-token (on all platforms),
202+ // so use workaround
203+ using ( cancellationToken . Register ( ( ) => stream . Dispose ( ) ) )
206204 {
207- if ( bufferOfs == bufferSize )
205+ var buffer = new byte [ NetworkReadBufferSize ] ;
206+ int bufferOfs = 0 ;
207+ int bufferSize = 0 ;
208+ Func < Task < char ? > > getChar = async ( ) =>
208209 {
209- // Networkstream.ReadAsync() doesn't honour the cancellation-token, so use workaround
210- using ( cancellationToken . Register ( ( ) => stream . Dispose ( ) ) )
210+ if ( bufferOfs == bufferSize )
211211 {
212212 try
213213 {
214214 bufferSize = await stream . ReadAsync ( buffer , 0 , buffer . Length ) . ConfigureAwait ( false ) ;
215215 }
216216 // netcoreapp2.x throws an IOException on stream disposal; others throw ObjectDispoesdException
217- catch ( Exception e ) when ( e is ObjectDisposedException || e is IOException )
217+ catch ( Exception e ) when ( e is ObjectDisposedException || e is IOException )
218218 {
219- cancellationToken . ThrowIfCancellationRequested ( ) ;
220- throw new OperationCanceledException ( ) ;
219+ throw new OperationCanceledException ( cancellationToken ) ;
221220 }
221+ // netcoreapp2.0 on Linux sometimes doesn't throw an exception on stream disposal in ReadAsync,
222+ // so check for cancellation afterwards
223+ cancellationToken . ThrowIfCancellationRequested ( ) ;
224+ if ( bufferSize == 0 )
225+ {
226+ // End of stream
227+ return null ;
228+ }
229+ bufferOfs = 0 ;
222230 }
223- if ( bufferSize == 0 )
224- {
225- // End of stream
226- return null ;
227- }
228- bufferOfs = 0 ;
229- }
230- byte b = buffer [ bufferOfs ++ ] ;
231- // HTTP headers are generally ASCII, but historically allowed ISO-8859-1.
232- // Non-ASCII bytes should be treated opaquely, not further processed (e.g. as UTF8).
233- return ( char ) b ;
234- } ;
235-
236- string requestLine = await ReadRequestLine ( getChar ) . ConfigureAwait ( false ) ;
237- var requestParams = ValidateAndGetRequestParams ( requestLine ) ;
238- await WaitForAllHeaders ( getChar ) . ConfigureAwait ( false ) ;
239- await WriteResponse ( stream , cancellationToken ) . ConfigureAwait ( false ) ;
240-
241- return requestParams ;
231+ byte b = buffer [ bufferOfs ++ ] ;
232+ // HTTP headers are generally ASCII, but historically allowed ISO-8859-1.
233+ // Non-ASCII bytes should be treated opaquely, not further processed (e.g. as UTF8).
234+ return ( char ) b ;
235+ } ;
236+
237+ string requestLine = await ReadRequestLine ( getChar ) . ConfigureAwait ( false ) ;
238+ var requestParams = ValidateAndGetRequestParams ( requestLine ) ;
239+ await WaitForAllHeaders ( getChar ) . ConfigureAwait ( false ) ;
240+ await WriteResponse ( stream , cancellationToken ) . ConfigureAwait ( false ) ;
241+
242+ return requestParams ;
243+ }
242244 }
243245
244246 private async Task < string > ReadRequestLine ( Func < Task < char ? > > getChar )
0 commit comments