public async Task <T> GetOrAdd <T>( Uri uri, EsiExecutionContext executionContext, Func <Task <CacheResponse <T> > > valueFactory) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } if (executionContext == null) { throw new ArgumentNullException(nameof(executionContext)); } if (valueFactory == null) { throw new ArgumentNullException(nameof(valueFactory)); } var(found, cached) = await TryGet <T>(uri, executionContext); if (found) { return(cached); } var response = await valueFactory(); await Set(uri, executionContext, response); return(response.Value); }
public async Task Should_forward_headers() { HttpRequestMessage request = null; var client = new FakeHttpMessageHandler() .Configure(new Uri("http://host/path"), r => { request = r; return(new HttpResponseMessage()); }) .ToClient(); var loader = CreateHttpLoader(client); var executionContext = new EsiExecutionContext( new Dictionary <string, IReadOnlyCollection <string> > { ["Accept"] = new[] { "text/html", "application/xhtml+xml" }, ["Cookie"] = new[] { "a=1; b=2" }, ["Connection"] = new[] { "Keep-Alive" } }, new Dictionary <string, IVariableValueResolver>()); await loader.Get(new Uri("http://host/path"), executionContext); request.Headers.TryGetValues("Accept", out var acceptValues).Should().Be.True(); acceptValues.Should().Have.SameSequenceAs("text/html", "application/xhtml+xml"); request.Headers.TryGetValues("Cookie", out var cookieValues).Should().Be.True(); cookieValues.Should().Have.SameSequenceAs("a=1; b=2"); request.Headers.Contains("Connection").Should().Be.False(); }
public static HttpRequestMessage Create(Uri uri, EsiExecutionContext executionContext) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } if (executionContext == null) { throw new ArgumentNullException(nameof(executionContext)); } var request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Add("X-Esi", "true"); foreach (var header in executionContext.RequestHeaders.Where(h => !SkipHeaders.Contains(h.Key))) { if (!request.Headers.TryAddWithoutValidation(header.Key, header.Value)) { request.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value); } } return(request); }
public async Task <HttpResponseMessage> Handle(Uri uri, EsiExecutionContext executionContext, HttpLoadDelegate next) { _log("pipeline before"); var response = await next(uri, executionContext); _log("pipeline after"); return(response); }
private Task <HttpResponseMessage> ExecuteRequest(Uri uri, EsiExecutionContext executionContext) { var request = _httpRequestMessageFactory(uri, executionContext); var httpClient = _httpClientFactory(uri); return(httpClient.SendAsync(request)); }
public Task <IEnumerable <string> > Execute(EsiTextFragment fragment, EsiExecutionContext executionContext) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } return(Task.FromResult <IEnumerable <string> >(new[] { fragment.Body })); }
private Task <HttpResponseMessage> Execute(Uri uri, EsiExecutionContext executionContext) { Task <HttpResponseMessage> Send(Uri u, EsiExecutionContext ec) => ExecuteRequest(uri, executionContext); return(_pipelines .Aggregate( (HttpLoadDelegate)Send, (next, pipeline) => async(u, ec) => await pipeline.Handle(u, ec, next))(uri, executionContext)); }
public async Task <IEnumerable <string> > Handle( EsiIncludeFragment fragment, EsiExecutionContext executionContext, ExecuteDelegate <EsiIncludeFragment> next) { var content = await next(fragment, executionContext); return(Wrap(content)); }
public async Task <IEnumerable <string> > Handle( EsiTextFragment fragment, EsiExecutionContext executionContext, ExecuteDelegate <EsiTextFragment> next) { var result = await next(new EsiTextFragment($"<{fragment.Body}>"), executionContext); var pre = new[] { "pre" }; var post = new[] { "post" }; return(pre.Concat(result).Concat(post)); }
private async Task <CacheResponse <IEsiFragment> > RequestAndParse( Uri uri, EsiExecutionContext executionContext) { var response = await _httpLoader.Get(uri, executionContext); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var fragment = _esiBodyParser.Parse(content); return(CacheResponse.Create(fragment, response.Headers.CacheControl, response.Headers.Vary.ToList())); }
public async Task Invoke(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.Response.StatusCode == 304 || context.Request.Headers.ContainsKey("X-Esi")) { await _next(context); return; } var executionContext = new EsiExecutionContext( context.Request.Headers.ToDictionary(), context.Request.GetVariablesFromContext()); var pageUri = context.Request.GetPageUri(); var(found, cachedResponse) = await _cache.TryGet <FragmentPageResponse>(pageUri, executionContext); IEsiFragment fragment; if (found) { context.Response.CopyHeaders(cachedResponse.Headers); fragment = cachedResponse.Fragment; } else { var acceptEncoding = context.Request.Headers[HeaderNames.AcceptEncoding]; context.Request.Headers[HeaderNames.AcceptEncoding] = StringValues.Empty; var body = await _next.TryIntercept(context); context.Request.Headers[HeaderNames.AcceptEncoding] = acceptEncoding; if (body == null) { return; } fragment = _parser.Parse(body); await StoreFragmentInCache(context, pageUri, executionContext, fragment); } var content = await _executor.Execute(fragment, executionContext); await context.Response.WriteAllAsync(content); }
public static IEnumerable <string> Resolve( EsiExecutionContext executionContext, VariableString variableString) { if (executionContext == null) { throw new ArgumentNullException(nameof(executionContext)); } if (variableString == null) { throw new ArgumentNullException(nameof(variableString)); } return(variableString.Parts .Select(o => ResolveStringPart(o, executionContext) ?? string.Empty)); }
public Task <IEnumerable <string> > Execute(EsiVarsFragment fragment, EsiExecutionContext executionContext) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } if (executionContext == null) { throw new ArgumentNullException(nameof(executionContext)); } var result = VariableStringResolver.Resolve(executionContext, fragment.Body); return(Task.FromResult(result)); }
public async Task <IEnumerable <string> > Execute(EsiTryFragment fragment, EsiExecutionContext executionContext) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } try { return(await _fragmentExecutor.Execute(fragment.AttemptFragment, executionContext)); } catch (Exception ex) { _log.Error(() => "Error when executing attempt fragment.", ex); return(await _fragmentExecutor.Execute(fragment.ExceptFragment, executionContext)); } }
private async Task StoreFragmentInCache( HttpContext context, Uri pageUri, EsiExecutionContext executionContext, IEsiFragment fragment) { CacheControlHeaderValue.TryParse( context.Response.Headers[HeaderNames.CacheControl], out var cacheControl); if (ShouldSetCache(context)) { var headers = context.Response.Headers.ToDictionary(); var pageResponse = new FragmentPageResponse(fragment, headers); var vary = context.Response.Headers[HeaderNames.Vary]; var cacheResponse = CacheResponse.Create(pageResponse, cacheControl, vary); await _cache.Set(pageUri, executionContext, cacheResponse); } }
private static string ResolveStringPart(object obj, EsiExecutionContext executionContext) { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } switch (obj) { case string s: return(s); case VariableExpression v: return(VariableResolver.ResolveValue(v, executionContext.Variables)); default: throw new Exception($"Unknown part type '{obj.GetType().Name}'."); } }
public async Task <IEnumerable <string> > Execute( EsiIncludeFragment fragment, EsiExecutionContext executionContext) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } var rawUrl = string.Concat(VariableStringResolver.Resolve(executionContext, fragment.Url)); var uri = _uriParser(rawUrl); var remoteFragment = await _cache.GetOrAdd( uri, executionContext, () => RequestAndParse(uri, executionContext)); return(await _fragmentExecutor.Execute(remoteFragment, executionContext)); }
public void Parse_and_build(string input, string expected) { var variables = new Dictionary <string, IVariableValueResolver> { ["HTTP_HOST"] = new SimpleVariableValueResolver(new Lazy <string>("example.com")), ["HTTP_COOKIE"] = new DictionaryVariableValueResolver(new Lazy <IReadOnlyDictionary <string, string> >( new Dictionary <string, string> { ["showPricesWithVat"] = "true" })) }; var executionContext = new EsiExecutionContext( new Dictionary <string, IReadOnlyCollection <string> >(), variables); var variableString = VariableStringParser.Parse(input); var actual = string.Concat(VariableStringResolver.Resolve(executionContext, variableString)); actual.Should().Be.EqualTo(expected); }
public async Task <HttpResponseMessage> Get(Uri uri, EsiExecutionContext executionContext) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } try { var response = await Execute(uri, executionContext); response.EnsureSuccessStatusCode(); return(response); } catch (Exception ex) { _log.Error(() => $"Error when loading '{uri}'.", ex); throw; } }
public Task <HttpResponseMessage> Handle(Uri uri, EsiExecutionContext executionContext, HttpLoadDelegate next) { var breakerPolicy = _breakerPolicies.GetOrAdd(_breakerKeyFactory(uri), _ => CreatePolicy()); return(breakerPolicy.ExecuteAsync(() => next(uri, executionContext))); }
public Task <IEnumerable <string> > Execute(EsiIgnoreFragment fragment, EsiExecutionContext executionContext) { return(Task.FromResult <IEnumerable <string> >(Array.Empty <string>())); }
public async Task <IEnumerable <string> > Execute(EsiCompositeFragment fragment, EsiExecutionContext executionContext) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } var tasks = fragment.Fragments .Select(fragment1 => _fragmentExecutor.Execute(fragment1, executionContext)); var results = await Task.WhenAll(tasks); return(results.SelectMany(s => s)); }
public async Task <IEnumerable <string> > Execute(EsiChooseFragment fragment, EsiExecutionContext executionContext) { if (fragment == null) { throw new ArgumentNullException(nameof(fragment)); } if (executionContext == null) { throw new ArgumentNullException(nameof(executionContext)); } var fragmentToShow = GetFirstSucceedingWhen(fragment.WhenFragments, executionContext.Variables) ?? fragment.OtherwiseFragment; return(await _fragmentExecutor.Execute(fragmentToShow, executionContext)); }
public Task <HttpResponseMessage> Handle(Uri uri, EsiExecutionContext executionContext, HttpLoadDelegate next) { return(_retryPolicy.ExecuteAsync(() => next(uri, executionContext))); }