示例#1
0
        private void Completion(Exception exception)
        {
            // NOTE (steveb): result.Return()/Throw() must be called by the coroutine;
            //      if the coroutine omits to call it, we will throw an exception
            //      since 'result' will not be marked as finished

            if (exception != null)
            {
                try {
                    // try to forward exception to recipient
                    exception.SetCoroutineInfo(this);
                    _result.Throw(exception);
                } catch {
                    // result object was already set
                    _log.ErrorExceptionFormat(exception, "Completion(): unhandled exception in {0} coroutine [1]", FullName);
                }
            }
            else if (!_result.HasFinished)
            {
                try {
                    exception = new CoroutineMissingResultException();
                    exception.SetCoroutineInfo(this);

                    // operation completed, but result hasn't been set
                    _result.Throw(exception);

                    // always log the fact that a coroutine failed to set a result; this is a pretty bad situation!
                    _log.Error("Completion() failed", exception);
                } catch {
                    // result object must have been set in the meantime
                    if (exception != null)
                    {
                        _log.ErrorExceptionFormat(exception, "Completion(): unhandled exception in {0} coroutine [2]", FullName);
                    }
                    else
                    {
                        _log.ErrorFormat("Coroutine.Completion(): missing result caused unhandled exception in {0} coroutine [3]", FullName);
                    }
                }
            }
        }
示例#2
0
        //--- Methods ---
        internal void Handler(Result <DreamMessage> result)
        {
            DreamMessage request;

            // check if previous feature handler threw an exception
            try {
                if (result.HasException)
                {
                    DreamAbortException abort = result.Exception as DreamAbortException;
                    if (abort != null)
                    {
                        // extract contained message
                        request = abort.Response;
                    }
                    else
                    {
                        // check if this is a cached response we need to forward
                        DreamCachedResponseException cached = result.Exception as DreamCachedResponseException;
                        if (cached != null)
                        {
                            _response.Throw(cached);
                            return;
                        }

                        // convert exception into message
                        DreamMessage          exceptionMessage = null;
                        ExceptionTranslator[] translators      = _context.Feature.ExceptionTranslators;
                        if (translators != null)
                        {
                            bool locallyAttachedContext = false;
                            try {
                                if (DreamContext.CurrentOrNull == null)
                                {
                                    _context.AttachToCurrentTaskEnv();
                                    locallyAttachedContext = true;
                                }
                                foreach (var translate in translators)
                                {
                                    exceptionMessage = translate(_context, result.Exception);
                                    if (exceptionMessage != null)
                                    {
                                        break;
                                    }
                                }
                            } finally {
                                if (locallyAttachedContext)
                                {
                                    _context.DetachFromTaskEnv();
                                }
                            }
                        }
                        if (exceptionMessage == null)
                        {
                            _log.ErrorExceptionFormat(result.Exception, "handler for {0}:{1} failed ({2})", _context.Verb, _context.Uri.ToString(false), _previousName);
                            exceptionMessage = DreamMessage.InternalError(result.Exception);
                        }
                        request = exceptionMessage;
                    }
                }
                else
                {
                    request = result.Value;
                }
            } catch (Exception e) {
                if (result.HasException)
                {
                    _log.ErrorExceptionFormat(result.Exception, "handler for {0}:{1} failed ({2}), cascading via processing exception '{3}'", _context.Verb, _context.Uri.ToString(false), _previousName, e);
                    request = DreamMessage.InternalError(result.Exception);
                }
                else
                {
                    _log.ErrorExceptionFormat(e, "handler for {0}:{1} failed completing stage '{2}'", _context.Verb, _context.Uri.ToString(false), _previousName);
                    request = DreamMessage.InternalError(e);
                }
            }

            // check if feature handler can handle this message
            if (!MainStage || request.IsSuccessful)
            {
                TaskEnv.ExecuteNew(() => Handler_DreamMessage(request));
            }
            else
            {
                // non-success messages skip the main stage
                _response.Return(request);
            }
        }
示例#3
0
        private Yield ResponseHandler(string verb, XUri requestUri, DreamMessage request, Result <DreamMessage> response, HttpListenerContext httpContext, Action <string> activity, Result result)
        {
            DreamMessage item = null;

            request.Close();
            try {
                activity("begin ResponseHandler");
                if (response.HasException)
                {
                    _log.ErrorExceptionFormat(response.Exception, "Request Failed [{0}:{1}]: {2}", verb, requestUri.Path, response.Exception.Message);
                }
                item = response.HasException ? DreamMessage.InternalError(response.Exception) : response.Value;

                // set status
                _log.TraceMethodCall("ResponseHandler: Status", item.Status, httpContext.Request.HttpMethod, httpContext.Request.Url);
                httpContext.Response.StatusCode = (int)item.Status;

                // remove internal headers
                item.Headers.DreamTransport = null;
                item.Headers.DreamPublicUri = null;

                // add out-going headers
                if (item.Headers.Server == null)
                {
                    item.Headers.Server = ServerSignature;
                }

                // create stream for response (this will force the creation of the 'Content-Length' header as well)
                Stream stream = item.ToStream();

                // copy headers
                httpContext.Response.Headers.Clear();
                foreach (KeyValuePair <string, string> pair in item.Headers)
                {
                    _log.TraceMethodCall("SendHttpResponse: Header", pair.Key, pair.Value);
                    HttpUtil.AddHeader(httpContext.Response, pair.Key, pair.Value);
                }

                // add set-cookie headers to response
                if (item.HasCookies)
                {
                    foreach (DreamCookie cookie in item.Cookies)
                    {
                        httpContext.Response.Headers.Add(DreamHeaders.SET_COOKIE, cookie.ToSetCookieHeader());
                    }
                }

                // disable keep alive behavior
                httpContext.Response.KeepAlive = false;

                // send message stream
                long size = item.ContentLength;
                if (((size == -1) || (size > 0)) && (stream != Stream.Null))
                {
                    activity(string.Format("pre CopyStream ({0} bytes)", size));
                    yield return(CopyStream(activity, stream, httpContext.Response.OutputStream, size, new Result <long>(DreamHostService.MAX_REQUEST_TIME)).CatchAndLog(_log));

                    activity("post CopyStream");
                }
                activity("pre Flush");
                httpContext.Response.OutputStream.Flush();
                activity("post Flush");
                result.Return();
                activity("end ResponseHandler");
            } finally {
                activity(null);
                if (item != null)
                {
                    item.Close();
                }
                httpContext.Response.Close();
            }
        }