public void SendResponse(MessageContext context, HttpResponsePacket response ) { if (disposed) throw new ObjectDisposedException("Subscriber has been disposed"); if (String.IsNullOrEmpty(context.ReplyToQueue)) return; if (conn == null) { //TODO: Log this -- it technically shouldn't happen. Also translate to a HTTP Unreachable because it means StartCallbackQueueConsumer didn't create a connection throw new ApplicationException("This is Bad"); } //TODO: Channel Pool this connection using (IModel channel = conn.CreateModel()) { BasicProperties basicProperties = new BasicProperties { CorrelationId = context.CorrelationId }; try { channel.BasicPublish(String.Empty, context.ReplyToQueue, basicProperties, response.Serialize()); } catch { //TODO: Log execption } } }
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 //HttpRequestMessage requestMsg; HttpResponse responseMsg = null; var msg = restbusContext.Request.ToServiceMessage(); var httpContext = new DefaultHttpContext(msg); await appFunc.Invoke(httpContext).ConfigureAwait(false); responseMsg = httpContext.Response; //if (!restbusContext.Request.TryGetHttpRequestMessage(appVirtualPath ?? (appVirtualPath = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath), out requestMsg)) //{ // responseMsg = new HttpResponseMessage(HttpStatusCode.BadRequest) { ReasonPhrase = "Bad Request" }; //} //TODO: Implement disposed //if (disposed) //{ // responseMsg = requestMsg.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, "The server is no longer available."); //} //else //{ // requestHandler.EnsureInitialized(); // // Add current synchronization context to request parameter // SynchronizationContext syncContext = SynchronizationContext.Current; // if (syncContext != null) // { // requestMsg.SetSynchronizationContext(syncContext); // } // // Add HttpConfiguration to request parameter // requestMsg.SetConfiguration(config); // // Ensure we have a principal, even if the host didn't give us one // IPrincipal originalPrincipal = Thread.CurrentPrincipal; // if (originalPrincipal == null) // { // Thread.CurrentPrincipal = anonymousPrincipal.Value; // } // // Ensure we have a principal on the request context (if there is a request context). // HttpRequestContext requestContext = requestMsg.GetRequestContext(); // if (requestContext == null) // { // requestContext = new RequestBackedHttpRequestContext(requestMsg); // // if the host did not set a request context we will also set it back to the request. // requestMsg.SetRequestContext(requestContext); // } // try // { // try // { // responseMsg = await requestHandler.SendMessageAsync(requestMsg, cancellationToken); // } // catch (HttpResponseException exception) // { // responseMsg = exception.Response; // } // catch (NullReferenceException exception) // { // // There is a bug in older versions of HttpRoutingDispatcher which causes a null reference exception when // // a route could not be found // // This bug can be triggered by sending a request for a url that doesn't have a route // // This commit fixes the bug https://github.com/ASP-NET-MVC/aspnetwebstack/commit/6a0c03f9e549966a7f806f8b696ec4cb2ec272e6#diff-c89c7bee3d225a037a6d04e8e4447460 // if (exception.TargetSite != null && exception.TargetSite.DeclaringType != null // && exception.TargetSite.DeclaringType.FullName == "System.Web.Http.Dispatcher.HttpRoutingDispatcher" // && exception.TargetSite.Name == "SendAsync") // { // //This is the bug, so send a 404 instead // const string NoRouteMatchedHttpPropertyKey = "MS_NoRouteMatched"; // requestMsg.Properties.Add(NoRouteMatchedHttpPropertyKey, true); // responseMsg = requestMsg.CreateErrorResponse( // HttpStatusCode.NotFound, // String.Format("No HTTP resource was found that matches the request URI '{0}'.", requestMsg.RequestUri)); // } // else // { // responseMsg = CreateResponseMessageFromException(exception); // } // } // catch (Exception exception) // { // responseMsg = CreateResponseMessageFromException(exception); // } // if (responseMsg == null) // { // //TODO: Not good, Log this // //TODO: derive exception from RestBus.Exceptions class // responseMsg = CreateResponseMessageFromException(new ApplicationException("Unable to get response")); // } // } // finally // { // Thread.CurrentPrincipal = originalPrincipal; // } //} //Send Response try { //TODO: Why can't the subscriber append the subscriber id itself from within sendresponse subscriber.SendResponse(restbusContext, MessageHelpers.ToHttpResponse(responseMsg, msg)); } catch { //TODO: Log SendResponse error } }
public void SendResponse(MessageContext context, HttpResponsePacket response ) { if (disposed) throw new ObjectDisposedException(GetType().FullName); var dispatch = context.Dispatch as MessageDispatch; if (dispatch != null) { //Ack request if(Settings.AckBehavior != SubscriberAckBehavior.Automatic && dispatch.Consumer.Model.IsOpen) { dispatch.Consumer.Model.BasicAck(dispatch.Delivery.DeliveryTag, false); //NOTE: The call above takes place in different threads silmultaneously //In which case multiple threads will be using the same channel at the same time. //It's okay in this case, because transmissions within a channel are synchronized, as seen in: //https://github.com/rabbitmq/rabbitmq-dotnet-client/blob/f16c093f6409e11d9d77115038cb224eb39468ec/projects/client/RabbitMQ.Client/src/client/impl/ModelBase.cs#L459 //and //https://github.com/rabbitmq/rabbitmq-dotnet-client/blob/f16c093f6409e11d9d77115038cb224eb39468ec/projects/client/RabbitMQ.Client/src/client/impl/SessionBase.cs#L177 } } //Exit method if no replyToQueue was specified. if (String.IsNullOrEmpty(context.ReplyToQueue)) return; if (_subscriberPool.Connection == null) { //TODO: Log this -- it technically shouldn't happen. Also translate to a HTTP Unreachable because it means StartCallbackQueueConsumer didn't create a connection throw new ApplicationException("This is Bad"); } //Add/Update Subscriber-Id header response.Headers[Common.Shared.SUBSCRIBER_ID_HEADER] = subscriberIdHeader; //Send response var pooler = _subscriberPool; AmqpModelContainer model = null; try { model = pooler.GetModel(ChannelFlags.None); BasicProperties basicProperties = new BasicProperties { CorrelationId = context.CorrelationId }; model.Channel.BasicPublish(String.Empty, context.ReplyToQueue, basicProperties, response.Serialize()); } finally { if(model != null) { model.Close(); } } }