Esempio n. 1
0
        /// <summary>
        /// Queries ESI to send a request.
        /// </summary>
        /// <typeparam name="T">The type of the response.</typeparam>
        /// <param name="method">The HTTP method to use when making the request.</param>
        /// <param name="request">The ESI request to make.</param>
        /// <param name="content">The content to send with the request.</param>
        /// <returns>The data from the ESI request.</returns>
        private async Task <EsiResult <T> > QueryEsiAsync <T>(HttpMethod method,
                                                              EsiRequestHeaders request, HttpContent content = null)
        {
            string url = await request.GetESIUrlAsync(Language).ConfigureAwait(false);

            var message = new HttpRequestMessage(method, url);

            if (content != null)
            {
                // Update content type if requested
                string contentType = request.ContentType.GetAttributeOfType <
                    DescriptionAttribute>()?.Description;
                if (contentType != null && content.Headers != null)
                {
                    content.Headers.ContentType.MediaType = contentType;
                }
                message.Content = content;
            }
            EsiResult <T> esiResult;

            // If previous request expiration is available, add ETag/If-Modified-Since
            request.CacheInfo?.AddRequestHeaders(message.Headers);
            try {
                using (var response = await client.SendAsync(message).ConfigureAwait(false)) {
                    esiResult = await HandleResponseAsync <T>(response);
                }
            } catch (IOException e) {
                // I/O errors become EsiResultStatus.NetworkError
                esiResult = new EsiResult <T>(EsiResultStatus.NetworkError, default(T), e);
            } catch (TimeoutException e) {
                // Time outs become EsiResultStatus.NetworkError
                esiResult = new EsiResult <T>(EsiResultStatus.NetworkError, default(T), e);
            } catch (OperationCanceledException e) {
                // Cancellations become EsiResultStatus.NetworkError
                esiResult = new EsiResult <T>(EsiResultStatus.NetworkError, default(T), e);
            }
            return(esiResult);
        }
Esempio n. 2
0
        /// <summary>
        /// Handles a response from ESI.
        /// </summary>
        /// <typeparam name="T">The type of the response.</typeparam>
        /// <param name="response">The response message from the server.</param>
        /// <returns>The data from the ESI request.</returns>
        private async Task <EsiResult <T> > HandleResponseAsync <T>(HttpResponseMessage response)
        {
            var           headers  = response.Headers;
            var           received = DateTime.UtcNow;
            EsiResult <T> result;

            headers.ThrowIfNull(nameof(headers));
            // Update error count
            int?ec = GetIntParam(headers, "X-Esi-Error-Limit-Remain");

            if (ec != null)
            {
                errorCount = (int)ec;
            }
            // Update error count refresh time, no more than 2 minutes in the future
            int?ecReset = GetIntParam(headers, "X-Esi-Error-Limit-Reset");

            if (ecReset != null)
            {
                errorCountRefresh = received.AddSeconds(Math.Min((int)ecReset, 120));
            }
            var status = ToEsiStatusCode(response.StatusCode);
            int pages  = GetIntParam(headers, "X-Pages") ?? 0;

            if (pages < 1)
            {
                pages = 1;
            }
            if (status == EsiResultStatus.OK)
            {
                try {
                    // Parse the ESI payload, content should not be null if response was OK
                    var serializer = new JsonSerializer {
                        DateTimeZoneHandling = DateTimeZoneHandling.Utc
                    };
                    var content = response.Content;
                    content.ThrowIfNull(nameof(content));
                    using (var jr = new JsonTextReader(new StreamReader(await content.
                                                                        ReadAsStreamAsync(), Encoding.UTF8))) {
                        jr.CloseInput = true;
                        // JSON parsing
                        result = new EsiResult <T>(status, serializer.Deserialize <T>(jr))
                        {
                            CacheInfo = new EsiCacheInfo(headers.ETag?.Tag, content.Headers.
                                                         Expires?.UtcDateTime ?? received),
                            Pages = pages
                        };
                        // Determine date and time on the server, no more laggy NIST time sync
                        var serverDate = headers.Date;
                        if (serverDate != null)
                        {
                            result.ServerTime = ((DateTimeOffset)serverDate).UtcDateTime;
                        }
                        jr.Close();
                    }
                } catch (JsonException e) {
                    // JSON parse failures become EsiResultStatus.Error
                    result = new EsiResult <T>(EsiResultStatus.Error, default(T), e);
                }
            }
            else
            {
                result = new EsiResult <T>(status);
            }
            return(result);
        }