private async Task FireOnResponseCompleted(ServiceMessage msg) { var onCompleted = msg._onCompleted; if (onCompleted != null) { foreach (var entry in onCompleted) { try { await entry.Key.Invoke(entry.Value); } catch (Exception ex) { ReportApplicationError(msg, ex); } } } }
private async Task FireOnResponseStarting(ServiceMessage msg) { var onStarting = msg._onStarting; if (onStarting != null) { try { foreach (var entry in onStarting) { await entry.Key.Invoke(entry.Value); } } catch (Exception ex) { ReportApplicationError(msg, ex); } } }
internal static HttpResponsePacket ToHttpResponsePacket(this ServiceMessage message) { if (message == null) { throw new ArgumentNullException("message"); } var response = new HttpResponsePacket(); var respFeature = message as IHttpResponseFeature; if (respFeature.Headers != null) { foreach (var hdr in respFeature.Headers) { response.Headers.Add(hdr.Key, hdr.Value); } } response.Version = HTTP_RESPONSE_VERSION; response.StatusCode = respFeature.StatusCode; if (String.IsNullOrEmpty(respFeature.ReasonPhrase)) { response.StatusDescription = ReasonPhrases.ToReasonPhrase(response.StatusCode) ?? "Unknown"; } else { response.StatusDescription = respFeature.ReasonPhrase; } if (message.OriginalResponseBody != null && message.OriginalResponseBody.CanRead) { //NOTE: OriginalResponseBody.CanRead will be false if the stream was disposed. response.Content = message.OriginalResponseBody.ToArray(); } //Add/Update Server header response.Headers["Server"] = HTTP_RESPONSE_SERVER_HEADER; return(response); }
internal static bool TryGetServiceMessage(this HttpRequestPacket request, out ServiceMessage message) { if (request == null) { throw new ArgumentNullException("request"); } message = new ServiceMessage(); //Build Request IHttpRequestFeature req = message as IHttpRequestFeature; Uri uri; try { uri = request.BuildUri(null, null); } catch { message = null; return(false); } req.Path = uri.AbsolutePath; req.Protocol = "HTTP/" + request.Version; req.QueryString = uri.Query; req.Method = request.Method; if (request.Content != null && request.Content.Length > 0) { message.CreateRequestBody(request.Content); } //Add Request Headers { var headers = new HeaderDictionary(); foreach (var hdr in request.Headers) { if (hdr.Key != null && hdr.Key.Trim().ToUpperInvariant() == "CONTENT-LENGTH") { continue; // Content-length is calculated based on actual content. } //NOTE: Client already folds Request Headers into RequestPacket, so there's no need to fold it again here. headers.Add(hdr.Key, hdr.Value.ToArray()); } if (message.OriginalRequestBody != null) { headers.Add("Content-Length", request.Content.Length.ToString()); } req.Headers = headers; } //Create Response message.CreateResponseBody(); IHttpResponseFeature resp = message as IHttpResponseFeature; resp.StatusCode = 200; //Add Response Headers { var headers = new HeaderDictionary(); headers.Add("Server", HTTP_RESPONSE_SERVER_HEADER[0]); resp.Headers = headers; } return(true); }
private void ReportApplicationError(ServiceMessage msg, Exception ex) { msg._applicationException = ex; //TODO: Log Application error }
/// <summary> /// Processes a request. /// </summary> private async Task ProcessRequest(MessageContext restbusContext, CancellationToken cancellationToken) { //NOTE: This method is called on a background thread and must be protected by an outer big-try catch TContext context = default(TContext); Exception appException = null; ServiceMessage msg = null; bool appInvoked = false; try { if (disposed) { msg = CreateResponse(HttpStatusCode.ServiceUnavailable, "The server is no longer available."); } else { if (!restbusContext.Request.TryGetServiceMessage(out msg)) { //Bad message msg = CreateResponse(HttpStatusCode.BadRequest, "Bad Request"); } else { context = application.CreateContext(msg); //Call application appInvoked = true; try { await application.ProcessRequestAsync(context).ConfigureAwait(false); } catch (Exception ex) { ReportApplicationError(msg, ex); } finally { //Call FireOnResponseStarting if message didn't encounter an exception. if (!msg.HasApplicationException) { await FireOnResponseStarting(msg).ConfigureAwait(false); } } } } if (msg.HasApplicationException) { appException = msg._applicationException; //If request encountered an exception then return an Internal Server Error (with empty body) response. msg.Dispose(); msg = CreateResponse(HttpStatusCode.InternalServerError, null); } //Send Response HttpResponsePacket responsePkt; try { responsePkt = msg.ToHttpResponsePacket(); } catch (Exception ex) { responsePkt = CreateResponseFromException(ex).ToHttpResponsePacket(); } try { subscriber.SendResponse(restbusContext, responsePkt); } catch { //TODO: Log SendResponse error } //Call OnCompleted callbacks if (appInvoked) { await FireOnResponseCompleted(msg).ConfigureAwait(false); } } finally { if (appInvoked) { application.DisposeContext(context, appException); } if (msg != null) { msg.Dispose(); } } }