Ejemplo n.º 1
0
        private void Handler_DreamMessage(DreamMessage request)
        {
            try {
                // grabbing context from FeatureChain (must remove it again from env before env completes, so that it doesn't get disposed)
                if (_context.IsTaskEnvDisposed)
                {
                    throw new InvalidOperationException("cannot go to next feature state with disposed context");
                }
                _context.AttachToCurrentTaskEnv();

                // check if request is authorized for service
                if ((_stage.Access != DreamAccess.Public) && (_context.Feature.Service.Self != null) && (_stage.Access > _context.Feature.Service.DetermineAccess(_context, request)))
                {
                    request.Close();
                    _log.WarnFormat("access '{0}' to feature '{1}' denied for '{2}'",
                                    _stage.Access,
                                    _context.Uri.AsPublicUri(),
                                    request.Headers.DreamService
                                    );
                    if (_log.IsDebugEnabled)
                    {
                        _log.DebugFormat("with service keys:");
                        foreach (DreamCookie c in request.Cookies)
                        {
                            if (c.Name != "service-key")
                            {
                                continue;
                            }
                            _log.DebugFormat("  path: {0}, key: {1}", c.Path, c.Value);
                        }
                    }

                    // removing context from env so that shared context is not disposed
                    _context.DetachFromTaskEnv();
                    _response.Return(DreamMessage.Forbidden("insufficient access privileges"));
                }
                else
                {
                    // invoke handler
                    Result <DreamMessage> inner = new Result <DreamMessage>(_response.Timeout, TaskEnv.Current).WhenDone(delegate(DreamMessage value) {
                        // removing context from env so that shared context is not disposed
                        _context.DetachFromTaskEnv();

                        // forward result to recipient
                        _response.Return(value);
                    }, delegate(Exception exception) {
                        // removing context from env so that shared context is not disposed
                        _context.DetachFromTaskEnv();

                        // forward exception to recipient
                        _response.Throw(exception);
                    });
                    _stage.Invoke(_context, request, inner);
                }
            } catch (Exception ex) {
                _response.Throw(ex);
            }
        }
Ejemplo n.º 2
0
        private void Handler_DreamMessage(DreamMessage request)
        {
            try {

                // grabbing context from FeatureChain (must remove it again from env before env completes, so that it doesn't get disposed)
                if(_context.IsTaskEnvDisposed) {
                    throw new InvalidOperationException("cannot go to next feature state with disposed context");
                }
                _context.AttachToCurrentTaskEnv();

                // check if request is authorized for service
                if((_stage.Access != DreamAccess.Public) && (_context.Feature.Service.Self != null) && (_stage.Access > _context.Feature.Service.DetermineAccess(_context, request))) {
                    request.Close();
                    _log.WarnFormat("access '{0}' to feature '{1}' denied for '{2}'",
                        _stage.Access,
                        _context.Uri.AsPublicUri(),
                        request.Headers.DreamService
                    );
                    if(_log.IsDebugEnabled) {
                        _log.DebugFormat("with service keys:");
                        foreach(DreamCookie c in request.Cookies) {
                            if(c.Name != "service-key") {
                                continue;
                            }
                            _log.DebugFormat("  path: {0}, key: {1}", c.Path, c.Value);
                        }
                    }

                    // removing context from env so that shared context is not disposed
                    _context.DetachFromTaskEnv();
                    _response.Return(DreamMessage.Forbidden("insufficient access privileges"));
                } else {

                    // invoke handler
                    Result<DreamMessage> inner = new Result<DreamMessage>(_response.Timeout, TaskEnv.Current).WhenDone(delegate(DreamMessage value) {

                        // removing context from env so that shared context is not disposed
                        _context.DetachFromTaskEnv();

                        // forward result to recipient
                        _response.Return(value);
                    }, delegate(Exception exception) {

                        // removing context from env so that shared context is not disposed
                        _context.DetachFromTaskEnv();

                        // forward exception to recipient
                        _response.Throw(exception);
                    });
                    _stage.Invoke(_context, request, inner);
                }
            } catch(Exception ex) {
                _response.Throw(ex);
            }
        }
Ejemplo n.º 3
0
Archivo: Plug.cs Proyecto: bjorg/DReAM
        /// <summary>
        /// Invoke the plug, but leave the stream unread so that the returned <see cref="DreamMessage"/> can be streamed.
        /// </summary>
        /// <param name="verb">Request verb.</param>
        /// <param name="request">Request message.</param>
        /// <param name="result">The <see cref="Result{DreamMessage}"/>instance to be returned by this method.</param>
        /// <returns>Synchronization handle.</returns>
        public Result<DreamMessage> InvokeEx(string verb, DreamMessage request, Result<DreamMessage> result) {
            if(verb == null) {
                throw new ArgumentNullException("verb");
            }
            if(request == null) {
                throw new ArgumentNullException("request");
            }
            if(request.Status != DreamStatus.Ok) {
                throw new ArgumentException("request status must be 200 (Ok)");
            }
            if(result == null) {
                throw new ArgumentNullException("response");
            }

            // determine which factory has the best match
            IPlugEndpoint match;
            XUri normalizedUri;
            FindPlugEndpoint(Uri, out match, out normalizedUri);

            // check if we found a match
            if(match == null) {
                request.Close();
                result.Return(new DreamMessage(DreamStatus.NoEndpointFound, null, XDoc.Empty));
                return result;
            }

            // add matching cookies from service or from global cookie jar
            DreamCookieJar cookies = CookieJar;

            // prepare request
            try {
                request = PreProcess(verb, Uri, normalizedUri, _headers, cookies, request);

                // check if custom pre-processing handlers are registered
                if(_preHandlers != null) {
                    foreach(var handler in _preHandlers) {
                        request = handler(verb, Uri, normalizedUri, request) ?? new DreamMessage(DreamStatus.RequestIsNull, null, XDoc.Empty);
                        if(request.Status != DreamStatus.Ok) {
                            result.Return(request);
                            return result;
                        }
                    }
                }
            } catch(Exception e) {
                request.Close();
                result.Return(new DreamMessage(DreamStatus.RequestFailed, null, new XException(e)));
                return result;
            }

            // Note (arnec): Plug never throws, so we usurp the passed result if it has a timeout
            // setting the result timeout on inner result manually
            var outerTimeout = result.Timeout;
            if(outerTimeout != TimeSpan.MaxValue) {
                result.Timeout = TimeSpan.MaxValue;
            }

            // if the governing result has a shorter timeout than the plug, it superceeds the plug timeout
            var timeout = outerTimeout < Timeout ? outerTimeout : Timeout;

            // prepare response handler
            var inner = new Result<DreamMessage>(timeout, TaskEnv.None).WhenDone(
                v => {
                    try {
                        var message = PostProcess(verb, Uri, normalizedUri, _headers, cookies, v);

                        // check if custom post-processing handlers are registered
                        if((message.Status == DreamStatus.MovedPermanently ||
                            message.Status == DreamStatus.Found ||
                            message.Status == DreamStatus.TemporaryRedirect) &&
                           AutoRedirect &&
                           request.IsCloneable
                        ) {
                            var redirectPlug = new Plug(message.Headers.Location, Timeout, Headers, null, null, null, CookieJar, (ushort)(MaxAutoRedirects - 1));
                            var redirectMessage = request.Clone();
                            request.Close();
                            redirectPlug.InvokeEx(verb, redirectMessage, new Result<DreamMessage>()).WhenDone(result.Return);
                        } else {
                            request.Close();
                            if(_postHandlers != null) {
                                foreach(var handler in _postHandlers) {
                                    message = handler(verb, Uri, normalizedUri, message) ?? new DreamMessage(DreamStatus.ResponseIsNull, null, XDoc.Empty);
                                }
                            }
                            result.Return(message);
                        }
                    } catch(Exception e) {
                        request.Close();
                        result.Return(new DreamMessage(DreamStatus.ResponseFailed, null, new XException(e)));
                    }
                },
                e => {

                    // an exception occurred somewhere during processing (not expected, but it could happen)
                    request.Close();
                    var status = DreamStatus.RequestFailed;
                    if(e is TimeoutException) {
                        status = DreamStatus.RequestConnectionTimeout;
                    }
                    result.Return(new DreamMessage(status, null, new XException(e)));
                }
            );

            // invoke message handler
            Coroutine.Invoke(match.Invoke, this, verb, normalizedUri, request, inner);
            return result;
        }