public async Task RoundTripIntegrationTest()
        {
            var cache = new InMemoryBlobCache();

            var cachingHandler = new RateLimitedHttpMessageHandler(new HttpClientHandler(), Priority.UserInitiated, cacheResultFunc: async(rq, resp, key, ct) => {
                var data = await resp.Content.ReadAsByteArrayAsync();
                await cache.Insert(key, data);
            });

            var client   = new HttpClient(cachingHandler);
            var origData = await client.GetStringAsync("http://httpbin.org/get");

            Assert.True(origData.Contains("origin"));
            Assert.Equal(1, (await cache.GetAllKeys()).Count());

            var offlineHandler = new OfflineHttpMessageHandler(async(rq, key, ct) => {
                return(await cache.Get(key));
            });

            client = new HttpClient(offlineHandler);
            var newData = await client.GetStringAsync("http://httpbin.org/get");

            Assert.Equal(origData, newData);

            bool shouldDie = true;

            try {
                await client.GetStringAsync("http://httpbin.org/gzip");
            } catch (Exception ex) {
                shouldDie = false;
                Console.WriteLine(ex);
            }

            Assert.False(shouldDie);
        }
Esempio n. 2
0
        public async Task CachingFunctionShouldPreserveHeaders()
        {
            var innerHandler = new TestHttpMessageHandler(_ =>
            {
                var ret = new HttpResponseMessage()
                {
                    Content    = new StringContent("foo", Encoding.UTF8),
                    StatusCode = HttpStatusCode.OK,
                };

                ret.Headers.ETag = new EntityTagHeaderValue("\"worifjw\"");
                return(Observable.Return(ret));
            });

            var etagResponses = new List <string>();
            var fixture       = new RateLimitedHttpMessageHandler(innerHandler, Priority.UserInitiated, cacheResultFunc: (rq, re, key, ct) =>
            {
                etagResponses.Add(re.Headers.ETag.Tag);
                return(Task.FromResult(true));
            });

            var client = new HttpClient(fixture);
            var resp   = await client.GetAsync(new Uri("http://lol/bar")).ConfigureAwait(false);

            Assert.Equal("\"worifjw\"", etagResponses[0]);
        }
        public async Task CachingFunctionShouldBeCalledWithContent()
        {
            var innerHandler = new TestHttpMessageHandler(_ => {
                var ret = new HttpResponseMessage()
                {
                    Content    = new StringContent("foo", Encoding.UTF8),
                    StatusCode = HttpStatusCode.OK,
                };

                ret.Headers.ETag = new EntityTagHeaderValue("\"worifjw\"");
                return(Observable.Return(ret));
            });

            var contentResponses = new List <byte[]>();
            var fixture          = new RateLimitedHttpMessageHandler(innerHandler, Priority.UserInitiated, cacheResultFunc: async(rq, re, key, ct) => {
                contentResponses.Add(await re.Content.ReadAsByteArrayAsync());
            });

            var client = new HttpClient(fixture);
            var str    = await client.GetStringAsync("http://lol/bar");

            Assert.Equal("foo", str);
            Assert.Equal(1, contentResponses.Count);
            Assert.Equal(3, contentResponses[0].Length);
        }
        public async Task RoundTripIntegrationTest()
        {
            var cache = new InMemoryBlobCache();

            var cachingHandler = new RateLimitedHttpMessageHandler(new HttpClientHandler(), Priority.UserInitiated, cacheResultFunc: async (rq, resp, key, ct) => {
                var data = await resp.Content.ReadAsByteArrayAsync();
                await cache.Insert(key, data);
            });

            var client = new HttpClient(cachingHandler);
            var origData = await client.GetStringAsync("http://httpbin.org/get");

            Assert.True(origData.Contains("origin"));
            Assert.Equal(1, (await cache.GetAllKeys()).Count());

            var offlineHandler = new OfflineHttpMessageHandler(async (rq, key, ct) => {
                return await cache.Get(key);
            });

            client = new HttpClient(offlineHandler);
            var newData = await client.GetStringAsync("http://httpbin.org/get");

            Assert.Equal(origData, newData);

            bool shouldDie = true;
            try {
                await client.GetStringAsync("http://httpbin.org/gzip");
            } catch (Exception ex) {
                shouldDie = false;
                Console.WriteLine(ex);
            }

            Assert.False(shouldDie);
        }
Esempio n. 5
0
        public async Task OnlyCacheRelevantMethods(string method, bool shouldCache)
        {
            var innerHandler = new TestHttpMessageHandler(_ =>
            {
                var ret = new HttpResponseMessage()
                {
                    Content    = new StringContent("foo", Encoding.UTF8),
                    StatusCode = HttpStatusCode.OK,
                };

                return(Observable.Return(ret));
            });

            var cached  = false;
            var fixture = new RateLimitedHttpMessageHandler(innerHandler, Priority.UserInitiated, cacheResultFunc: (rq, re, key, ct) =>
            {
                cached = true;
                return(Task.FromResult(true));
            });

            var client  = new HttpClient(fixture);
            var request = new HttpRequestMessage(new HttpMethod(method), "http://lol/bar");
            await client.SendAsync(request).ConfigureAwait(false);

            Assert.Equal(shouldCache, cached);
        }
Esempio n. 6
0
        public T Get <T>(RequestPriority priority)
        {
            var messageHandler = new RateLimitedHttpMessageHandler(BaseHandler, (Priority)priority);
            var client         = new HttpClient(messageHandler)
            {
                BaseAddress = new Uri(BaseAddress)
            };

            return(RestService.For <T>(client));
        }
Esempio n. 7
0
        /// <summary>
        /// Create an
        /// </summary>
        /// <param name="priority"></param>
        /// <returns></returns>
        private TApi CreateApi(Priority priority)
        {
            var handler = new RateLimitedHttpMessageHandler(new TokenNativeMessageHandler(_getToken, _configuration.UserAgent, _configuration.AppId)
            {
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
            }, priority);

            var client = new HttpClient(handler)
            {
                BaseAddress = new Uri(_configuration.BaseUrl),
            };

            var restService = RestService.For <TApi>(client, new RefitSettings
            {
                UrlParameterFormatter = new DateTimeRefit()
            });

            return(restService);
        }
        public static Lazy <IEducationApi> GetClient(Priority priority)
        {
            var nativeHandler = new NativeMessageHandler();

            if (nativeHandler.SupportsAutomaticDecompression)
            {
                nativeHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
            }
            var rateLimitedHandler = new RateLimitedHttpMessageHandler(nativeHandler, priority);
            var authEnabledHandler =
                new AuthenticatedHttpClientHandler(() => BaseAuthenticationService.GetAuthorizationHeaderAsync(),
                                                   rateLimitedHandler);
            var rateLimitedClient = new HttpClient(authEnabledHandler)
            {
                BaseAddress = BaseAddress
            };

            return(new Lazy <IEducationApi>(() => RestService.For <IEducationApi>(rateLimitedClient)));
        }
        public async Task CachingFunctionShouldPreserveHeaders()
        {
            var innerHandler = new TestHttpMessageHandler(_ => {
                var ret = new HttpResponseMessage() {
                    Content = new StringContent("foo", Encoding.UTF8),
                    StatusCode = HttpStatusCode.OK,
                };

                ret.Headers.ETag = new EntityTagHeaderValue("\"worifjw\"");
                return Observable.Return(ret);
            });

            var etagResponses = new List<string>();
            var fixture = new RateLimitedHttpMessageHandler(innerHandler, Priority.UserInitiated, cacheResultFunc: (rq, re, key, ct) => {
                etagResponses.Add(re.Headers.ETag.Tag);
                return Task.FromResult(true);
            });

            var client = new HttpClient(fixture);
            var resp = await client.GetAsync("http://lol/bar");
            Assert.Equal("\"worifjw\"", etagResponses[0]);
        }
        public async Task CachingFunctionShouldBeCalledWithContent()
        {
            var innerHandler = new TestHttpMessageHandler(_ => {
                var ret = new HttpResponseMessage() {
                    Content = new StringContent("foo", Encoding.UTF8),
                    StatusCode = HttpStatusCode.OK,
                };

                ret.Headers.ETag = new EntityTagHeaderValue("\"worifjw\"");
                return Observable.Return(ret);
            });

            var contentResponses = new List<byte[]>();
            var fixture = new RateLimitedHttpMessageHandler(innerHandler, Priority.UserInitiated, cacheResultFunc: async (rq, re, key, ct) => {
                contentResponses.Add(await re.Content.ReadAsByteArrayAsync());
            });

            var client = new HttpClient(fixture);
            var str = await client.GetStringAsync("http://lol/bar");

            Assert.Equal("foo", str);
            Assert.Equal(1, contentResponses.Count);
            Assert.Equal(3, contentResponses[0].Length);
        }
        protected override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request is null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            var method = request.Method;

            if (method != HttpMethod.Get && method != HttpMethod.Head && method != HttpMethod.Options)
            {
                return(base.SendAsync(request, cancellationToken));
            }

            if (_maxBytesToRead != null && _maxBytesToRead.Value < 0)
            {
                var tcs = new TaskCompletionSource <HttpResponseMessage>();
                tcs.SetCanceled();
                return(tcs.Task);
            }

            var priority = (int)Priority.UserInitiated;

            if (request.Properties.TryGetValue("Priority", out var priorityObject))
            {
                var priorityValue = (int)priorityObject;
                if (priorityValue >= 0)
                {
                    priority = priorityValue;
                }
            }

            var key       = RateLimitedHttpMessageHandler.UniqueKeyForRequest(request);
            var realToken = new CancellationTokenSource();
            var ret       = new InflightRequest(() =>
            {
                lock (_inflightResponses)
                {
                    _inflightResponses.Remove(key);
                }

                realToken.Cancel();
            });

            lock (_inflightResponses)
            {
                if (_inflightResponses.ContainsKey(key))
                {
                    var val = _inflightResponses[key];
                    val.AddRef();
                    cancellationToken.Register(val.Cancel);

                    return(val.Response.ToTask(cancellationToken));
                }

                _inflightResponses[key] = ret;
            }

            cancellationToken.Register(ret.Cancel);

            var queue = _opQueue ?? NetCache.OperationQueue;

            queue.Enqueue(
                priority,
                null,
                async() =>
            {
                try
                {
                    var resp = await base.SendAsync(request, realToken.Token).ConfigureAwait(false);

                    if (_maxBytesToRead != null && resp.Content?.Headers.ContentLength != null)
                    {
                        _maxBytesToRead -= resp.Content.Headers.ContentLength;
                    }

                    return(resp);
                }
                finally
                {
                    lock (_inflightResponses)
                    {
                        _inflightResponses.Remove(key);
                    }
                }
            },
                realToken.Token).ToObservable().Subscribe(ret.Response);

            return(ret.Response.ToTask(cancellationToken));
        }
        public async Task OnlyCacheRelevantMethods(string method, bool shouldCache)
        {
            var innerHandler = new TestHttpMessageHandler(_ => {
                var ret = new HttpResponseMessage()
                {
                    Content = new StringContent("foo", Encoding.UTF8),
                    StatusCode = HttpStatusCode.OK,
                };

                return Observable.Return(ret);
            });

            var cached = false;
            var fixture = new RateLimitedHttpMessageHandler(innerHandler, Priority.UserInitiated, cacheResultFunc: (rq, re, key, ct) => {
                cached = true;
                return Task.FromResult(true);
            });

            var client = new HttpClient(fixture);
            var request = new HttpRequestMessage(new HttpMethod(method), "http://lol/bar");
            await client.SendAsync(request);

            Assert.Equal(shouldCache, cached);
        }