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); }
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); }
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); }
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)); }
/// <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); }