Ejemplo n.º 1
0
        internal static void HandleRequestStateChange(RequestEventInfo @event)
        {
            HTTPRequest source = @event.SourceRequest;

            switch (@event.State)
            {
            case HTTPRequestStates.Processing:
                if ((!source.UseStreaming && source.UploadStream == null) || source.EnableTimoutForStreaming)
                {
                    BestHTTP.Extensions.Timer.Add(new TimerData(TimeSpan.FromSeconds(1), @event.SourceRequest, AbortRequestWhenTimedOut));
                }
                break;

            case HTTPRequestStates.Aborted:
            case HTTPRequestStates.ConnectionTimedOut:
            case HTTPRequestStates.TimedOut:
            case HTTPRequestStates.Error:
            case HTTPRequestStates.Finished:
                if (source.Callback != null)
                {
                    try
                    {
                        source.Callback(source, source.Response);
                    }
                    catch (Exception ex)
                    {
                        HTTPManager.Logger.Exception("RequestEventHelper", "HandleRequestStateChange " + @event.State, ex);
                    }

                    //if (source.Response != null && source.Response.Data != null)
                    //    VariableSizedBufferPool.Release(source.Response.Data);
                }

                source.Dispose();

                HostManager.GetHost(source.CurrentUri.Host)
                .GetHostDefinition(HostDefinition.GetKeyForRequest(source))
                .TryToSendQueuedRequests();
                break;
            }
        }
        internal static void HandleRequestStateChange(RequestEventInfo @event)
        {
            HTTPRequest source = @event.SourceRequest;

            // Because there's a race condition between setting the request's State in its Abort() function running on Unity's main thread
            //  and the HTTP1/HTTP2 handlers running on an another one.
            // Because of these race conditions cases violating expectations can be:
            //  1.) State is finished but the response null
            //  2.) State is (Connection)TimedOut and the response non-null
            // We have to make sure that no callbacks are called twice and in the request must be in a consistent state!

            //    State        | Request
            //   ---------     +---------
            // 1                  Null
            //   Finished      |   Skip
            //   Timeout/Abort |   Deliver
            //
            // 2                 Non-Null
            //   Finished      |    Deliver
            //   Timeout/Abort |    Skip

            switch (@event.State)
            {
            case HTTPRequestStates.Queued:
                source.QueuedAt = DateTime.UtcNow;
                if ((!source.UseStreaming && source.UploadStream == null) || source.EnableTimoutForStreaming)
                {
                    BestHTTP.Extensions.Timer.Add(new TimerData(TimeSpan.FromSeconds(1), @event.SourceRequest, AbortRequestWhenTimedOut));
                }
                break;

            case HTTPRequestStates.ConnectionTimedOut:
            case HTTPRequestStates.TimedOut:
            case HTTPRequestStates.Error:
            case HTTPRequestStates.Aborted:
                source.Response = null;
                goto case HTTPRequestStates.Finished;

            case HTTPRequestStates.Finished:

#if !BESTHTTP_DISABLE_CACHING
                // Here we will try to load content for a failed load. Failed load is a request with ConnectionTimedOut, TimedOut or Error state.
                // A request with Finished state but response with status code >= 500 also something that we will try to load from the cache.
                // We have to set what we going to try to load here too (other place is inside IsCachedEntityExpiresInTheFuture) as we don't want to load a cached content for
                // a request that just finished without any problem!

                try
                {
                    bool tryLoad = !source.DisableCache && source.State != HTTPRequestStates.Aborted && (source.State != HTTPRequestStates.Finished || source.Response == null || source.Response.StatusCode >= 500);
                    if (tryLoad && Caching.HTTPCacheService.IsCachedEntityExpiresInTheFuture(source))
                    {
                        HTTPManager.Logger.Information("RequestEventHelper", "IsCachedEntityExpiresInTheFuture check returned true! CurrentUri: " + source.CurrentUri.ToString(), source.Context);

                        PlatformSupport.Threading.ThreadedRunner.RunShortLiving <HTTPRequest>((req) =>
                        {
                            // Disable any other cache activity.
                            req.DisableCache = true;

                            var originalState = req.State;
                            if (Connections.ConnectionHelper.TryLoadAllFromCache("RequestEventHelper", req, req.Context))
                            {
                                if (req.State != HTTPRequestStates.Finished)
                                {
                                    req.State = HTTPRequestStates.Finished;
                                }
                                else
                                {
                                    RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(req, HTTPRequestStates.Finished));
                                }
                            }
                            else
                            {
                                HTTPManager.Logger.Information("RequestEventHelper", "TryLoadAllFromCache failed to load! CurrentUri: " + req.CurrentUri.ToString(), source.Context);

                                // If for some reason it couldn't load we place back the request to the queue.
                                RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(req, originalState));
                            }
                        }, source);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    HTTPManager.Logger.Exception("RequestEventHelper", string.Format("HandleRequestStateChange - Cache probe - CurrentUri: \"{0}\" State: {1} StatusCode: {2}", source.CurrentUri, source.State, source.Response != null ? source.Response.StatusCode : 0), ex, source.Context);
                }
#endif

                source.Timing.Add(TimingEventNames.Queued_For_Disptach);
                source.Timing.Add(TimingEventNames.Finished, DateTime.Now - source.Timing.Start);

                if (source.Callback != null)
                {
                    try
                    {
                        source.Callback(source, source.Response);

                        source.Timing.Add(TimingEventNames.Callback);

                        if (HTTPManager.Logger.Level <= Loglevels.Information)
                        {
                            HTTPManager.Logger.Information("RequestEventHelper", "Finishing request. Timings: " + source.Timing.ToString(), source.Context);
                        }
                    }
                    catch (Exception ex)
                    {
                        HTTPManager.Logger.Exception("RequestEventHelper", "HandleRequestStateChange " + @event.State, ex, source.Context);
                    }
                }

                source.Dispose();

                HostManager.GetHost(source.CurrentUri.Host)
                .GetHostDefinition(HostDefinition.GetKeyForRequest(source))
                .TryToSendQueuedRequests();
                break;
            }
        }
#pragma warning restore

        public static void EnqueueRequestEvent(RequestEventInfo @event)
        {
            requestEventQueue.Enqueue(@event);
        }
        internal static void HandleRequestStateChange(RequestEventInfo @event)
        {
            HTTPRequest source = @event.SourceRequest;

            switch (@event.State)
            {
            case HTTPRequestStates.Processing:
                if ((!source.UseStreaming && source.UploadStream == null) || source.EnableTimoutForStreaming)
                {
                    BestHTTP.Extensions.Timer.Add(new TimerData(TimeSpan.FromSeconds(1), @event.SourceRequest, AbortRequestWhenTimedOut));
                }
                break;

            case HTTPRequestStates.ConnectionTimedOut:
            case HTTPRequestStates.TimedOut:
            case HTTPRequestStates.Error:
            case HTTPRequestStates.Aborted:
            case HTTPRequestStates.Finished:

#if !BESTHTTP_DISABLE_CACHING
                // Here we will try to load content for a failed load. Failed load is a request with ConnectionTimedOut, TimedOut or Error state.
                // A request with Finished state but response with status code >= 500 also something that we will try to load from the cache.
                // We have to set what we going to try to load here too (other place is inside IsCachedEntityExpiresInTheFuture) as we don't want to load a cached content for
                // a request that just finished without any problem!

                try
                {
                    bool tryLoad = !source.DisableCache && source.State != HTTPRequestStates.Aborted && (source.State != HTTPRequestStates.Finished || source.Response == null || source.Response.StatusCode >= 500);
                    if (tryLoad && Caching.HTTPCacheService.IsCachedEntityExpiresInTheFuture(source))
                    {
                        HTTPManager.Logger.Information("RequestEventHelper", "IsCachedEntityExpiresInTheFuture check returned true! CurrentUri: " + source.CurrentUri.ToString(), source.Context);

                        PlatformSupport.Threading.ThreadedRunner.RunShortLiving <HTTPRequest>((req) =>
                        {
                            // Disable any other cache activity.
                            req.DisableCache = true;

                            var originalState = req.State;
                            if (Connections.ConnectionHelper.TryLoadAllFromCache("RequestEventHelper", req, req.Context))
                            {
                                if (req.State != HTTPRequestStates.Finished)
                                {
                                    req.State = HTTPRequestStates.Finished;
                                }
                                else
                                {
                                    RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(req, HTTPRequestStates.Finished));
                                }
                            }
                            else
                            {
                                HTTPManager.Logger.Information("RequestEventHelper", "TryLoadAllFromCache failed to load! CurrentUri: " + req.CurrentUri.ToString(), source.Context);

                                // If for some reason it couldn't load we place back the request to the queue.
                                RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(req, originalState));
                            }
                        }, source);
                        break;
                    }
                }
                catch (Exception ex)
                {
                    HTTPManager.Logger.Exception("RequestEventHelper", string.Format("HandleRequestStateChange - Cache probe - CurrentUri: \"{0}\" State: {1} StatusCode: {2}", source.CurrentUri, source.State, source.Response != null ? source.Response.StatusCode : 0), ex, source.Context);
                }
#endif

                if (source.Callback != null)
                {
                    try
                    {
                        source.Callback(source, source.Response);
                    }
                    catch (Exception ex)
                    {
                        HTTPManager.Logger.Exception("RequestEventHelper", "HandleRequestStateChange " + @event.State, ex, source.Context);
                    }
                }

                source.Dispose();

                HostManager.GetHost(source.CurrentUri.Host)
                .GetHostDefinition(HostDefinition.GetKeyForRequest(source))
                .TryToSendQueuedRequests();
                break;
            }
        }