public void HandleResponse(Session session)
        {
            var key = $"{session.RequestMethod}_{session.hostname}_{session.url}";

            _logger.Verbose("{ThisMethod} for {Method} {Url} {StatusCode}", nameof(HandleResponse), session.RequestMethod, session.url, session.responseCode);

            if (IsResponseSuccessful(session))
            {
                _logger.Verbose("Response was successful");

                if (!_responseCache.IsCached(key))
                {
                    _logger.Info("Response was not previously cached, adding");

                    var responseBodyBytes = new byte[session.responseBodyBytes.Length];
                    session.responseBodyBytes.CopyTo(responseBodyBytes, 0);

                    _responseCache.Add(key, new ResponseCacheItem
                    {
                        ResponseBodyBytes = responseBodyBytes,
                        ResponseCode      = session.responseCode
                    });
                }
                else
                {
                    _logger.Verbose("Response was previously cached");
                }
            }
            else
            {
                _logger.Info("Response was not successful");

                if (_responseCache.IsCached(key))
                {
                    _logger.Info("Response was previously cached");

                    var cachedSession = _responseCache.Get(key);
                    session.responseCode = cachedSession.ResponseCode;

                    var newResponseBodyBytes = new byte[cachedSession.ResponseBodyBytes.Length];
                    cachedSession.ResponseBodyBytes.CopyTo(newResponseBodyBytes, 0);
                    session.responseBodyBytes = newResponseBodyBytes;

                    _logger.Info("Replaced failed response with cached response");
                }
                else
                {
                    _logger.Info("Response was not previously cached");
                }
            }
        }
예제 #2
0
        public async Task <string> ProcessMessage(PostUrlParameters urlParameters, Stream requestStream)
        {
            var requestMessage = BuildRequest(urlParameters, requestStream);

            var key = requestMessage.GetDuplicationKey();

            // 如果是正在处理中的重复消息, 则返回等待处理完成返回处理结果
            var responseText = await GetResponseFromExecution(urlParameters, key).ConfigureAwait(false);

            if (responseText != null)
            {
                OnResponseGenerated(responseText, ResponseSource.Executing);
                return(responseText);
            }

            // 如果是已处理的重复消息, 则直接返回待处理结果
            responseText = await GetResponseFromCache(key);

            if (responseText != null)
            {
                OnResponseGenerated(responseText, ResponseSource.Cache);
                return(responseText);
            }

            var handler = CreateHandler();
            var task    = handler.Handle(requestMessage);

            // 开始处理后, 保存正在处理的消息
            var done = task.IsCompleted;

            if (!done)
            {
                _executionDictionary.Add(key, task);
            }

            var responseMessage = await task.ConfigureAwait(false);

            responseText = SerializeResponse(urlParameters, responseMessage);

            // 处理完成后, 从正在处理转移到处理完成
            await _responseCache.Add(key, responseText).ConfigureAwait(false);

            if (!done)
            {
                _executionDictionary.Remove(key);
            }

            OnResponseGenerated(responseText, ResponseSource.New);
            return(responseText);
        }
예제 #3
0
        private async Task <HttpResponseMessage> ProcessResponseCaching(HttpResponseMessage response)
        {
            if (!ResponseIsCachable(response))
            {
                return(response);
            }

            var requestUrl = response.RequestMessage.RequestUri.AbsoluteUri;

            if (response.StatusCode == HttpStatusCode.NotModified)
            {
                var cachedReponse = _cache.Get(requestUrl);

                if (cachedReponse != null)
                {
                    var base64DecodedContent = Convert.FromBase64String(cachedReponse);
                    var stream = new MemoryStream(base64DecodedContent);

                    response.Content = new StreamContent(stream);
                }
            }

            var memoryStream   = new MemoryStream();
            var responseStream = await response.Content.ReadAsStreamAsync();

            responseStream.CopyTo(memoryStream);

            var bytes = memoryStream.ToArray();
            var base64EncodedContent = Convert.ToBase64String(bytes);

            var maxAgeHeader = response.Headers.CacheControl.MaxAge.Value.TotalSeconds;

            var eTag = ParseReponseEtag(response);

            _cache.Add(requestUrl,
                       base64EncodedContent,
                       TimeSpan.FromSeconds(maxAgeHeader),
                       eTag);

            memoryStream.Position = 0;
            response.Content      = new StreamContent(memoryStream);
            responseStream.Dispose();
            return(response);
        }
예제 #4
0
        public async Task <string> ProcessMessage(PostUrlParameters urlParameters, Stream requestStream)
        {
            var requestMessage = BuildRequest(urlParameters, requestStream);

            var key = requestMessage.GetDuplicationKey();

            ResponseSource source;

            // 如果是正在处理中的重复消息, 则返回等待处理完成返回处理结果
            var responseMessage = await GetResponseFromExecution(urlParameters, key).ConfigureAwait(false);

            if (responseMessage != null)
            {
                source = ResponseSource.Executing;
            }
            else
            {
                // 如果是已处理的重复消息, 则直接返回待处理结果
                responseMessage = await GetResponseFromCache(key).ConfigureAwait(false);

                if (responseMessage != null)
                {
                    source = ResponseSource.Cache;
                }
                else
                {
                    var  handler = CreateHandler();
                    bool done    = false;
                    try
                    {
                        var task = handler.Handle(requestMessage);

                        // 开始处理后, 保存正在处理的消息
                        done = task.IsCompleted;
                        if (!done)
                        {
                            _executionDictionary.Add(key, task);
                        }

                        responseMessage = await task.ConfigureAwait(false);
                    }
                    finally
                    {
                        if (handler is IDisposable d)
                        {
                            d.Dispose();
                        }
                    }

                    // 处理完成后, 从正在处理转移到处理完成
                    await _responseCache.Add(key, responseMessage).ConfigureAwait(false);

                    if (!done)
                    {
                        _executionDictionary.Remove(key);
                    }

                    source = ResponseSource.New;
                }
            }

            var responseText = responseMessage.Serialize();

            OnResponseGenerated(responseText, source);

            if (responseMessage.EncryptionRequired)
            {
                responseText = EncryptResponse(urlParameters, responseText);
            }

            return(responseText);
        }