/// <summary> /// Returns a handler for incoming Web stream requests. /// </summary> /// <param name="route"> /// The handler. /// </param> /// <param name="controller"> /// The controller. /// </param> /// <param name="args"> /// The request parameters. /// </param> /// <param name="environment"> /// The environment. /// </param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A handler for incoming Web stream requests. /// </returns> public static async Task HttpRequestHandler( this ControllerRoute route, object controller, IDictionary<string, string> args, IOwinContext environment, CancellationToken cancellationToken) { var response = environment.Response; var pump = new MutuallyExclusiveTaskExecutor(); var outgoing = GetObservableFromHandler(() => route.Invoke(controller, args, _ => Observable.Empty<string>())); var headersWritten = new[] { false }; response.Headers.Set("Transfer-Encoding", "Chunked"); response.ContentType = "application/json"; // Hook up the outgoing message pump to the response body. var subscription = outgoing.Subscribe( msg => pump.Schedule( async () => { try { if (!headersWritten[0]) { headersWritten[0] = true; // Set the response headers. response.StatusCode = 200; } await response.WriteAsync(msg, cancellationToken); await response.Body.FlushAsync(cancellationToken); } catch { pump.Complete(); throw; } }), e => pump.Schedule( async () => { try { if (!headersWritten[0]) { // Set the response headers. response.StatusCode = 500; headersWritten[0] = true; } await response.WriteAsync(e.ToString(), cancellationToken); await response.Body.FlushAsync(cancellationToken); } finally { pump.Complete(); } }), () => pump.Schedule( () => { if (!headersWritten[0]) { // No content. response.StatusCode = 204; response.Body.Close(); response.Body = Stream.Null; headersWritten[0] = true; } pump.Complete(); return Task.FromResult(0); })); // When the cancellation token is cancelled, unsubscribe. cancellationToken.Register(subscription.Dispose); try { await pump.Run(cancellationToken); } finally { subscription.Dispose(); } }
/// <summary> /// Returns a handler for incoming Web stream requests. /// </summary> /// <param name="route"> /// The handler. /// </param> /// <param name="controller"> /// The controller. /// </param> /// <param name="args"> /// The request parameters. /// </param> /// <param name="environment"> /// The environment. /// </param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns> /// A handler for incoming Web stream requests. /// </returns> public static async Task HttpRequestHandler( this ControllerRoute route, object controller, IDictionary <string, string> args, IOwinContext environment, CancellationToken cancellationToken) { var response = environment.Response; var pump = new MutuallyExclusiveTaskExecutor(); var outgoing = GetObservableFromHandler(() => route.Invoke(controller, args, _ => Observable.Empty <string>())); var headersWritten = new[] { false }; response.Headers.Set("Transfer-Encoding", "Chunked"); response.ContentType = "application/json"; // Hook up the outgoing message pump to the response body. var subscription = outgoing.Subscribe( msg => pump.Schedule( async() => { try { if (!headersWritten[0]) { headersWritten[0] = true; // Set the response headers. response.StatusCode = 200; } await response.WriteAsync(msg, cancellationToken); await response.Body.FlushAsync(cancellationToken); } catch { pump.Complete(); throw; } }), e => pump.Schedule( async() => { try { if (!headersWritten[0]) { // Set the response headers. response.StatusCode = 500; headersWritten[0] = true; } await response.WriteAsync(e.ToString(), cancellationToken); await response.Body.FlushAsync(cancellationToken); } finally { pump.Complete(); } }), () => pump.Schedule( () => { if (!headersWritten[0]) { // No content. response.StatusCode = 204; response.Body.Close(); response.Body = Stream.Null; headersWritten[0] = true; } pump.Complete(); return(Task.FromResult(0)); })); // When the cancellation token is cancelled, unsubscribe. cancellationToken.Register(subscription.Dispose); try { await pump.Run(cancellationToken); } finally { subscription.Dispose(); } }