void InvokeRequestHandler(RequestCommandAndStream requestAndStream) { ListenerCommand.RequestCommand requestCommand = requestAndStream.RequestCommand; Uri requestUri = new Uri(this.listener.Address, requestCommand.RequestTarget); var listenerContext = new RelayedHttpListenerContext( this.listener, requestUri, requestCommand.Id, requestCommand.Method, requestCommand.RequestHeaders); listenerContext.Request.SetRemoteAddress(requestCommand.RemoteEndpoint); listenerContext.Response.StatusCode = HttpStatusCode.OK; listenerContext.Response.OutputStream = new ResponseStream(this, listenerContext); RelayEventSource.Log.HybridHttpRequestReceived(listenerContext.TrackingContext, requestCommand.Method); Stream requestStream = requestAndStream.Stream; if (requestStream != null) { listenerContext.Request.HasEntityBody = true; listenerContext.Request.InputStream = requestStream; } var requestHandler = this.listener.RequestHandler; if (requestHandler != null) { try { RelayEventSource.Log.HybridHttpInvokingUserRequestHandler(); requestHandler(listenerContext); } catch (Exception userException) when(!Fx.IsFatal(userException)) { RelayEventSource.Log.HandledExceptionAsWarning(this, userException); listenerContext.Response.StatusCode = HttpStatusCode.InternalServerError; listenerContext.Response.StatusDescription = this.TrackingContext.EnsureTrackableMessage(SR.RequestHandlerException); listenerContext.Response.CloseAsync().Fork(this); return; } } else { RelayEventSource.Log.HybridHttpConnectionMissingRequestHandler(); listenerContext.Response.StatusCode = HttpStatusCode.NotImplemented; listenerContext.Response.StatusDescription = this.TrackingContext.EnsureTrackableMessage(SR.RequestHandlerMissing); listenerContext.Response.CloseAsync().Fork(this); } }
void InvokeRequestHandler(RequestCommandAndStream requestAndStream) { ListenerCommand.RequestCommand requestCommand = requestAndStream.RequestCommand; Uri requestUri = new Uri(this.listener.Address, requestCommand.RequestTarget); var listenerContext = new RelayedHttpListenerContext( this.listener, requestUri, requestCommand.Id, requestCommand.Method, requestCommand.RequestHeaders); listenerContext.Request.SetRemoteAddress(requestCommand.RemoteEndpoint); listenerContext.Response.StatusCode = HttpStatusCode.OK; listenerContext.Response.OutputStream = new ResponseStream(this, listenerContext); RelayEventSource.Log.HybridHttpRequestReceived(listenerContext.TrackingContext, requestCommand.Method); Stream requestStream = requestAndStream.Stream; if (requestStream != null) { listenerContext.Request.HasEntityBody = true; listenerContext.Request.InputStream = requestStream; } var requestHandler = this.listener.RequestHandler; if (requestHandler != null) { try { RelayEventSource.Log.HybridHttpInvokingUserRequestHandler(); requestHandler(listenerContext); } catch (Exception userException) when(!Fx.IsFatal(userException)) { RelayEventSource.Log.Warning( listenerContext, $"The Relayed Listener's custom RequestHandler threw an exception. {listenerContext.TrackingContext}, Exception: {userException}"); return; } } else { RelayEventSource.Log.HandledExceptionAsWarning(this, new InvalidOperationException("RequestHandler is not set.")); } }
public static async Task CreateAsync(HybridConnectionListener listener, ListenerCommand.RequestCommand requestCommand, WebSocket controlWebSocket) { var hybridHttpConnection = new HybridHttpConnection(listener, controlWebSocket, requestCommand.Address); // In this method we're holding up the listener's control connection. // Do only what we need to do (receive any request body from control channel) and then let this Task complete. bool requestOverControlConnection = requestCommand.Body.HasValue; var requestAndStream = new RequestCommandAndStream(requestCommand, null); if (requestOverControlConnection) { requestAndStream = await hybridHttpConnection.ReceiveRequestBodyOverControlAsync(requestCommand).ConfigureAwait(false); } // ProcessFirstRequestAsync runs without blocking the listener control connection: Task.Run(() => hybridHttpConnection.ProcessFirstRequestAsync(requestAndStream)).Fork(hybridHttpConnection); }
async Task ProcessFirstRequestAsync(RequestCommandAndStream requestAndStream) { try { var requestCommand = requestAndStream.RequestCommand; if (!requestCommand.Body.HasValue) { // Need to rendezvous to get the real RequestCommand requestAndStream = await this.ReceiveRequestOverRendezvousAsync().ConfigureAwait(false); } this.InvokeRequestHandler(requestAndStream); } catch (Exception e) when(!Fx.IsFatal(e)) { RelayEventSource.Log.HandledExceptionAsWarning(this.listener, e); await this.CloseAsync().ConfigureAwait(false); } }