Exemplo n.º 1
0
        public static async Task EndHttpHandlerRequestAsync(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Func <IResponse, Task> afterHeaders = null)
        {
            if (!skipHeaders)
            {
                httpRes.ApplyGlobalResponseHeaders();
            }

            if (afterHeaders != null)
            {
                await afterHeaders(httpRes);
            }

            var req = httpRes.Request;

            if (req != null && !req.Items.ContainsKey(Keywords.HasLogged))
            {
                HostContext.TryResolve <IRequestLogger>()?
                .Log(req, req.Dto, null, TimeSpan.Zero);
            }

            if (!skipClose && !httpRes.IsClosed)
            {
                httpRes.Close();
            }

            HostContext.CompleteRequest(req);
        }
        public override void Execute(IRequest req, IResponse res, object requestDto)
        {
            var authErrorMessage = "";
            try
            {
                // Perform security check
                if (CanExecute(req))
                    return;
            }
            catch (System.Exception ex)
            {
                authErrorMessage = ex.Message;
                var message = string.Format("Blocked unauthorized request: {0} {1} by ip = {2} due to {3}",
                    req.Verb,
                    req.AbsoluteUri,
                    req.UserHostAddress ?? "unknown",
                    authErrorMessage);
                Log.Error(message);
            }

            // Security failed!
            var responseMessage = "You are not authorized. " + authErrorMessage;

            res.StatusCode = (int)HttpStatusCode.Unauthorized;
            res.StatusDescription = responseMessage;
            res.AddHeader(HttpHeaders.WwwAuthenticate, string.Format("{0} realm=\"{1}\"", "", "custom api"));
            res.ContentType = "text/plain";
            res.Write(responseMessage);
            res.Close();
        }
Exemplo n.º 3
0
 /// <summary>
 /// End an MQ Request
 /// </summary>
 public static void EndMqRequest(this IResponse httpRes, bool skipClose = false)
 {
     if (!skipClose && !httpRes.IsClosed)
     {
         httpRes.Close();
     }
     HostContext.CompleteRequest(httpRes.Request);
 }
Exemplo n.º 4
0
 /// <summary>
 /// End a HttpHandler Request
 /// </summary>
 public static void EndHttpHandlerRequest(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Action <IResponse> afterHeaders = null)
 {
     if (!skipHeaders)
     {
         httpRes.ApplyGlobalResponseHeaders();
     }
     afterHeaders?.Invoke(httpRes);
     if (!skipClose && !httpRes.IsClosed)
     {
         httpRes.Close();
     }
     HostContext.CompleteRequest(httpRes.Request);
 }
Exemplo n.º 5
0
 public static void SendResponse(IResponse response, byte[] data, int statusCode, Dictionary <string, string> headers)
 {
     if (headers != null)
     {
         headers.Keys.Each(key =>
         {
             response.Headers.Add(key, headers[key]);
         });
     }
     response.OutputStream.Write(data, 0, data.Length);
     response.StatusCode = statusCode;
     response.Close();
 }
Exemplo n.º 6
0
 public static void SendResponse(IResponse response, string output, int statusCode = 200, Encoding encoding = null, Dictionary <string, string> headers = null)
 {
     encoding = encoding ?? Encoding.UTF8;
     if (headers != null)
     {
         headers.Keys.Each(key =>
         {
             response.Headers.Add(key, headers[key]);
         });
     }
     byte[] data = encoding.GetBytes(output);
     response.OutputStream.Write(data, 0, data.Length);
     response.StatusCode = statusCode;
     response.Close();
 }
Exemplo n.º 7
0
        private void ProcessResult(IResponse response, RateLimitResult rateLimitResult)
        {
            SetLimitHeaders(response, rateLimitResult);

            // NOTE By default we return an empty RateLimitResult which will have an 'Access' value of null.. which we default to true. Is this correct?
            if (!rateLimitResult?.Access ?? true)
            {
                if (log.IsDebugEnabled)
                {
                    var request = response.Request;
                    log.Debug(
                        $"Rate limit exceeded for {request.AbsoluteUri}, user {KeyGenerator.GetConsumerId(request)}. Returning status code: {LimitStatusCode}");
                }
                response.StatusCode        = LimitStatusCode;
                response.StatusDescription = StatusDescription;
                response.Close();
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// End a HttpHandler Request
        /// </summary>
        public static void EndHttpHandlerRequest(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Action <IResponse> afterHeaders = null)
        {
            if (!skipHeaders)
            {
                httpRes.ApplyGlobalResponseHeaders();
            }
            if (afterHeaders != null)
            {
                afterHeaders(httpRes);
            }
            if (!skipClose)
            {
                httpRes.Close();
            }

            //skipHeaders used when Apache+mod_mono doesn't like:
            //response.OutputStream.Flush();
            //response.Close();
        }
Exemplo n.º 9
0
        /// <summary>
        /// End a HttpHandler Request
        /// </summary>
        public static void EndHttpHandlerRequest(this IResponse httpRes, bool skipHeaders = false, bool skipClose = false, Action <IResponse> afterHeaders = null)
        {
            //if (!skipHeaders) httpRes.ApplyGlobalResponseHeaders();

            afterHeaders?.Invoke(httpRes);

            var req = httpRes.Request;

            if (req != null && !req.Items.ContainsKey(Keywords.HasLogged))
            {
                HostContext.TryResolve <IRequestLogger>()?.Log(req, req.Dto, httpRes.Dto, TimeSpan.Zero);
            }

            if (!skipClose && !httpRes.IsClosed)
            {
                httpRes.Close();
            }

            HostContext.CompleteRequest(req);
        }
Exemplo n.º 10
0
        private void OpenConnection(IConnection connection, string data, Action initializeCallback, Action <Exception> errorCallback)
        {
            // If we're reconnecting add /connect to the url
            bool reconnecting    = initializeCallback == null;
            var  callbackInvoker = new ThreadSafeInvoker();

            var url = (reconnecting ? connection.Url : connection.Url + "connect") + GetReceiveQueryString(connection, data);

            Action <IRequest> prepareRequest = PrepareRequest(connection);

#if NET35
            Debug.WriteLine(String.Format(System.Globalization.CultureInfo.InvariantCulture, "SSE: GET {0}", (object)url));
#else
            Debug.WriteLine("SSE: GET {0}", (object)url);
#endif

            _httpClient.GetAsync(url, request =>
            {
                prepareRequest(request);

                request.Accept = "text/event-stream";
            }).ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    Exception exception = task.Exception.Unwrap();
                    if (!ExceptionHelper.IsRequestAborted(exception))
                    {
                        if (errorCallback != null)
                        {
                            callbackInvoker.Invoke((cb, ex) => cb(ex), errorCallback, exception);
                        }
                        else if (reconnecting)
                        {
                            // Only raise the error event if we failed to reconnect
                            connection.OnError(exception);

                            Reconnect(connection, data);
                        }
                    }
                }
                else
                {
                    IResponse response = task.Result;
                    Stream stream      = response.GetResponseStream();

                    var eventSource = new EventSourceStreamReader(stream);
                    bool retry      = true;

                    connection.Items[EventSourceKey] = eventSource;

                    eventSource.Opened = () =>
                    {
                        if (initializeCallback != null)
                        {
                            callbackInvoker.Invoke(initializeCallback);
                        }

                        if (reconnecting && connection.ChangeState(ConnectionState.Reconnecting, ConnectionState.Connected))
                        {
                            // Raise the reconnect event if the connection comes back up
                            connection.OnReconnected();
                        }
                    };

                    eventSource.Message = sseEvent =>
                    {
                        if (sseEvent.Type == EventType.Data)
                        {
                            if (sseEvent.Data.Equals("initialized", StringComparison.OrdinalIgnoreCase))
                            {
                                return;
                            }

                            bool timedOut;
                            bool disconnected;
                            ProcessResponse(connection, sseEvent.Data, out timedOut, out disconnected);

                            if (disconnected)
                            {
                                retry = false;
                            }
                        }
                    };

                    eventSource.Closed = exception =>
                    {
                        if (exception != null && !ExceptionHelper.IsRequestAborted(exception))
                        {
                            // Don't raise exceptions if the request was aborted (connection was stopped).
                            connection.OnError(exception);
                        }

                        // See http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.close.aspx
                        response.Close();

                        if (retry)
                        {
                            Reconnect(connection, data);
                        }
                        else
                        {
                            connection.Stop();
                        }
                    };

                    eventSource.Start();
                }
            });

            if (errorCallback != null)
            {
                TaskAsyncHelper.Delay(ConnectionTimeout).Then(() =>
                {
                    callbackInvoker.Invoke((conn, cb) =>
                    {
                        // Stop the connection
                        Stop(conn);

                        // Connection timeout occured
                        cb(new TimeoutException());
                    },
                                           connection,
                                           errorCallback);
                });
            }
        }
Exemplo n.º 11
0
        private void OpenConnection(IConnection connection,
                                    string data,
                                    Action initializeCallback,
                                    Action <Exception> errorCallback)
        {
            // If we're reconnecting add /connect to the url
            bool                    _reconnecting   = initializeCallback == null;
            string                  _url            = (_reconnecting ? connection.Url : connection.Url + "connect");
            Action <IRequest>       _prepareRequest = PrepareRequest(connection);
            EventSignal <IResponse> _signal;

            if (shouldUsePost(connection))
            {
                _url += GetReceiveQueryString(connection, data);
                Debug.WriteLine(string.Format("SSE: POST {0}", _url));

                _signal = m_httpClient.PostAsync(
                    _url,
                    request =>
                {
                    _prepareRequest(request);
                    request.Accept = "text/event-stream";
                },
                    new Dictionary <string, string> {
                    {
                        "groups", GetSerializedGroups(connection)
                    }
                });
            }
            else
            {
                _url += GetReceiveQueryStringWithGroups(connection, data);
                Debug.WriteLine(string.Format("SSE: GET {0}", _url));

                _signal = m_httpClient.GetAsync(
                    _url,
                    request =>
                {
                    _prepareRequest(request);
                    request.Accept = "text/event-stream";
                });
            }

            _signal.Finished += (sender, e) =>
            {
                if (e.Result.IsFaulted)
                {
                    Exception _exception = e.Result.Exception.GetBaseException();

                    if (!HttpBasedTransport.IsRequestAborted(_exception))
                    {
                        if (errorCallback != null &&
                            Interlocked.Exchange(ref m_initializedCalled, 1) == 0)
                        {
                            errorCallback(_exception);
                        }
                        else if (_reconnecting)
                        {
                            // Only raise the error event if we failed to reconnect
                            connection.OnError(_exception);
                        }
                    }

                    if (_reconnecting)
                    {
                        // Retry
                        Reconnect(connection, data);
                        return;
                    }
                }
                else
                {
                    // Get the reseponse stream and read it for messages
                    IResponse         _response = e.Result;
                    Stream            _stream   = _response.GetResponseStream();
                    AsyncStreamReader _reader   = new AsyncStreamReader(
                        _stream,
                        connection,
                        () =>
                    {
                        if (Interlocked.CompareExchange(ref m_initializedCalled, 1, 0) == 0)
                        {
                            initializeCallback();
                        }
                    },
                        () =>
                    {
                        _response.Close();
                        Reconnect(connection, data);
                    });

                    if (_reconnecting)
                    {
                        // Raise the reconnect event if the connection comes back up
                        connection.OnReconnected();
                    }

                    _reader.StartReading();

                    // Set the reader for this connection
                    connection.Items[m_readerKey] = _reader;
                }
            };

            if (initializeCallback != null)
            {
                int _tryed = 0;
                while (true)
                {
                    _tryed++;
                    Debug.Write("Checking if connection initialized for the '" + _tryed.ToString() + "' time: ");

                    Thread.Sleep(m_connectionTimeout);
                    if (Interlocked.CompareExchange(ref m_initializedCalled, 1, 0) == 0)
                    {
                        if (_tryed < m_connectionRetry)
                        {
                            Debug.WriteLine("failed.");
                            continue;
                        }

                        Debug.WriteLine("giving up.");

                        // Stop the connection
                        Stop(connection);

                        // Connection timeout occurred
                        errorCallback(new TimeoutException());

                        break;
                    }
                    else
                    {
                        Debug.WriteLine("success.");
                        break;
                    }
                }
            }
        }
Exemplo n.º 12
0
        private void OpenConnection(IConnection connection, string data, Action initializeCallback, Action <Exception> errorCallback)
        {
            // If we're reconnecting add /connect to the url
            bool reconnecting = initializeCallback == null;

            var url = (reconnecting ? connection.Url : connection.Url + "connect") + GetReceiveQueryString(connection, data);

            Action <IRequest> prepareRequest = PrepareRequest(connection);

            Debug.WriteLine("SSE: GET {0}", (object)url);

            _httpClient.GetAsync(url, request =>
            {
                prepareRequest(request);

                request.Accept = "text/event-stream";
            }).ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    var exception = task.Exception.Unwrap();
                    if (!ExceptionHelper.IsRequestAborted(exception))
                    {
                        if (errorCallback != null &&
                            Interlocked.Exchange(ref _initializedCalled, 1) == 0)
                        {
                            errorCallback(exception);
                        }
                        else if (reconnecting)
                        {
                            // Only raise the error event if we failed to reconnect
                            connection.OnError(exception);
                        }
                    }

                    if (reconnecting && !CancellationToken.IsCancellationRequested)
                    {
                        connection.State = ConnectionState.Reconnecting;

                        // Retry
                        Reconnect(connection, data);
                        return;
                    }
                }
                else
                {
                    IResponse response = task.Result;
                    Stream stream      = response.GetResponseStream();

                    var eventSource = new EventSourceStreamReader(stream);
                    bool retry      = true;

                    // When this fires close the event source
                    CancellationToken.Register(() => eventSource.Close());

                    eventSource.Opened = () =>
                    {
                        if (Interlocked.CompareExchange(ref _initializedCalled, 1, 0) == 0)
                        {
                            initializeCallback();
                        }

                        if (reconnecting)
                        {
                            // Change the status to connected
                            connection.State = ConnectionState.Connected;

                            // Raise the reconnect event if the connection comes back up
                            connection.OnReconnected();
                        }
                    };

                    eventSource.Error = connection.OnError;

                    eventSource.Message = sseEvent =>
                    {
                        if (sseEvent.Type == EventType.Data)
                        {
                            if (sseEvent.Data.Equals("initialized", StringComparison.OrdinalIgnoreCase))
                            {
                                return;
                            }

                            bool timedOut;
                            bool disconnected;
                            ProcessResponse(connection, sseEvent.Data, out timedOut, out disconnected);

                            if (disconnected)
                            {
                                retry = false;
                            }
                        }
                    };

                    eventSource.Closed = () =>
                    {
                        response.Close();

                        if (retry && !CancellationToken.IsCancellationRequested)
                        {
                            // If we're retrying then just go again
                            connection.State = ConnectionState.Reconnecting;

                            Reconnect(connection, data);
                        }
                        else
                        {
                            connection.Stop();
                        }
                    };

                    if (!CancellationToken.IsCancellationRequested)
                    {
                        eventSource.Start();
                    }
                }
            });

            if (initializeCallback != null)
            {
                TaskAsyncHelper.Delay(ConnectionTimeout).Then(() =>
                {
                    if (Interlocked.CompareExchange(ref _initializedCalled, 1, 0) == 0)
                    {
                        // Stop the connection
                        Stop(connection);

                        // Connection timeout occured
                        errorCallback(new TimeoutException());
                    }
                });
            }
        }
Exemplo n.º 13
0
        private void OpenConnection(IConnection connection,
                                    string data,
                                    CancellationToken disconnectToken,
                                    Action initializeCallback,
                                    Action <Exception> errorCallback)
        {
            // If we're reconnecting add /connect to the url
            bool reconnecting    = initializeCallback == null;
            var  callbackInvoker = new ThreadSafeInvoker();
            var  requestDisposer = new Disposer();

            var      url     = (reconnecting ? connection.Url : connection.Url + "connect") + GetReceiveQueryString(connection, data);
            IRequest request = null;

#if NET35
            Debug.WriteLine(String.Format(CultureInfo.InvariantCulture, "SSE: GET {0}", (object)url));
#else
            Debug.WriteLine("SSE: GET {0}", (object)url);
#endif

            HttpClient.GetAsync(url, req =>
            {
                request = req;
                connection.PrepareRequest(request);

                request.Accept = "text/event-stream";
            }).ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    Exception exception = task.Exception.Unwrap();
                    if (!ExceptionHelper.IsRequestAborted(exception))
                    {
                        if (errorCallback != null)
                        {
                            callbackInvoker.Invoke((cb, ex) => cb(ex), errorCallback, exception);
                        }
                        else if (reconnecting)
                        {
                            // Only raise the error event if we failed to reconnect
                            connection.OnError(exception);

                            Reconnect(connection, data, disconnectToken);
                        }
                    }
                    requestDisposer.Dispose();
                }
                else
                {
                    IResponse response = task.Result;
                    Stream stream      = response.GetResponseStream();

                    var eventSource = new EventSourceStreamReader(stream);
                    bool retry      = true;

                    var esCancellationRegistration = disconnectToken.SafeRegister(es =>
                    {
                        retry = false;
                        es.Close();
                    }, eventSource);

                    eventSource.Opened = () =>
                    {
                        if (!reconnecting)
                        {
                            callbackInvoker.Invoke(initializeCallback);
                        }
                        else if (connection.ChangeState(ConnectionState.Reconnecting, ConnectionState.Connected))
                        {
                            // Raise the reconnect event if the connection comes back up
                            connection.OnReconnected();
                        }
                    };

                    eventSource.Message = sseEvent =>
                    {
                        if (sseEvent.EventType == EventType.Data)
                        {
                            if (sseEvent.Data.Equals("initialized", StringComparison.OrdinalIgnoreCase))
                            {
                                return;
                            }

                            bool timedOut;
                            bool disconnected;
                            ProcessResponse(connection, sseEvent.Data, out timedOut, out disconnected);

                            if (disconnected)
                            {
                                retry = false;
                                connection.Disconnect();
                            }
                        }
                    };

                    eventSource.Closed = exception =>
                    {
                        bool isRequestAborted = false;

                        if (exception != null)
                        {
                            // Check if the request is aborted
                            isRequestAborted = ExceptionHelper.IsRequestAborted(exception);

                            if (!isRequestAborted)
                            {
                                // Don't raise exceptions if the request was aborted (connection was stopped).
                                connection.OnError(exception);
                            }
                        }

                        // Skip reconnect attempt for aborted requests
                        if (!isRequestAborted && retry)
                        {
                            Reconnect(connection, data, disconnectToken);
                        }
                    };

                    // See http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.close.aspx
                    eventSource.Disabled = () =>
                    {
                        requestDisposer.Dispose();
                        esCancellationRegistration.Dispose();
                        response.Close();
                    };

                    eventSource.Start();
                }
            });

            var requestCancellationRegistration = disconnectToken.SafeRegister(req =>
            {
                if (req != null)
                {
                    // This will no-op if the request is already finished.
                    req.Abort();
                }

                if (errorCallback != null)
                {
                    callbackInvoker.Invoke((cb, token) =>
                    {
#if NET35 || WINDOWS_PHONE
                        cb(new OperationCanceledException(Resources.Error_ConnectionCancelled));
#else
                        cb(new OperationCanceledException(Resources.Error_ConnectionCancelled, token));
#endif
                    }, errorCallback, disconnectToken);
                }
            }, request);

            requestDisposer.Set(requestCancellationRegistration);

            if (errorCallback != null)
            {
                TaskAsyncHelper.Delay(ConnectionTimeout).Then(() =>
                {
                    callbackInvoker.Invoke((conn, cb) =>
                    {
                        connection.Disconnect();

                        // Connection timeout occurred
                        cb(new TimeoutException());
                    },
                                           connection,
                                           errorCallback);
                });
            }
        }
        private void ProcessResult(IResponse response, RateLimitResult rateLimitResult)
        {
            SetLimitHeaders(response, rateLimitResult);

            // NOTE By default we return an empty RateLimitResult which will have an 'Access' value of null.. which we default to true. Is this correct?
            if (!rateLimitResult?.Access ?? true)
            {
                if (log.IsDebugEnabled)
                {
                    var request = response.Request;
                    log.Debug(
                        $"Rate limit exceeded for {request.AbsoluteUri}, user {KeyGenerator.GetConsumerId(request)}. Returning status code: {LimitStatusCode}");
                }
                response.StatusCode = LimitStatusCode;
                response.StatusDescription = StatusDescription;
                response.Close();
            }
        }