Skip to content

Instantly share code, notes, and snippets.

@ElakkuvanR
Created October 16, 2021 10:38
Show Gist options
  • Select an option

  • Save ElakkuvanR/a066de531c9e875308d9743ba27440a2 to your computer and use it in GitHub Desktop.

Select an option

Save ElakkuvanR/a066de531c9e875308d9743ba27440a2 to your computer and use it in GitHub Desktop.
#nullable enable
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Mvp.Foundation.Caching.Providers;
using Mvp.Foundation.CustomMiddleware.Extension;
using Newtonsoft.Json;
using Sitecore.LayoutService.Client;
using Sitecore.LayoutService.Client.Exceptions;
using Sitecore.LayoutService.Client.Request;
using Sitecore.LayoutService.Client.RequestHandlers;
using Sitecore.LayoutService.Client.Response;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
namespace Mvp.Foundation.CustomMiddleware.Handlers
{
public class CustomHttpRequestHandler : ILayoutRequestHandler
{
private readonly ISitecoreLayoutSerializer _serializer;
private readonly HttpClient _client;
private readonly IOptionsSnapshot<HttpLayoutRequestHandlerOptions> _options;
private readonly ILogger<CustomHttpRequestHandler> _logger;
private readonly IOptions<SitecoreLayoutClientOptions> _layoutClientOptions;
private readonly IOptionsSnapshot<SitecoreLayoutRequestOptions> _layoutRequestOptions;
private readonly ICachingProvider _cachingProvider;
public CustomHttpRequestHandler(HttpClient client, ISitecoreLayoutSerializer serializer, IOptionsSnapshot<HttpLayoutRequestHandlerOptions> options, ILogger<CustomHttpRequestHandler> logger, IOptions<SitecoreLayoutClientOptions> layoutClientOptions, IOptionsSnapshot<SitecoreLayoutRequestOptions> layoutRequestOptions, ICachingProvider cachingprovider)
{
_client = client;
_serializer = serializer;
_options = options;
_logger = logger;
_layoutClientOptions = layoutClientOptions;
_cachingProvider = cachingprovider;
}
/// <inheritdoc />
public async Task<SitecoreLayoutResponse> Request(SitecoreLayoutRequest request, string handlerName)
{
Stopwatch timer = Stopwatch.StartNew();
SitecoreLayoutResponseContent content = null;
string cacheKey = request.GenerateCacheKeyForHttpRequest();
ILookup<string, string> metadata = null;
List<SitecoreLayoutServiceClientException> errors = new List<SitecoreLayoutServiceClientException>();
try
{
HttpLayoutRequestHandlerOptions options = _options.Get(handlerName);
HttpRequestMessage httpRequestMessage;
try
{
httpRequestMessage = BuildMessage(request, options);
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug($"Layout Service Http Request Message : {httpRequestMessage}");
}
}
catch (Exception ex)
{
errors = AddError(errors, new SitecoreLayoutServiceMessageConfigurationException(ex));
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug($"An error configuring the HTTP message : {ex}");
}
return new SitecoreLayoutResponse(request, errors);
}
// Read the layout response from Distributed Cache
string contentText = _cachingProvider.GetCacheValue(cacheKey);
if (!string.IsNullOrEmpty(contentText))
{
content = _serializer.Deserialize(contentText);
timer.Stop();
_logger.LogDebug($"Total Execution Time : {timer.ElapsedMilliseconds}");
return new SitecoreLayoutResponse(request, errors)
{
Content = content,
Metadata = metadata
};
}
HttpResponseMessage httpResponse = await GetResponseAsync(httpRequestMessage).ConfigureAwait(continueOnCapturedContext: false);
if (_logger.IsEnabled(LogLevel.Debug))
{
_logger.LogDebug($"Layout Service Http Response : {httpResponse}");
}
int responseStatusCode = (int)httpResponse.StatusCode;
if (!httpResponse.IsSuccessStatusCode)
{
int num = responseStatusCode;
List<SitecoreLayoutServiceClientException> list;
if (responseStatusCode == 404)
{
list = AddError(errors, new ItemNotFoundSitecoreLayoutServiceClientException(), responseStatusCode);
}
else
{
list = ((responseStatusCode >= 400 && responseStatusCode < 500) ? AddError(errors, new InvalidRequestSitecoreLayoutServiceClientException(), responseStatusCode) : ((responseStatusCode < 500) ? AddError(errors, new SitecoreLayoutServiceClientException(), responseStatusCode) : AddError(errors, new InvalidResponseSitecoreLayoutServiceClientException(new SitecoreLayoutServiceServerException()), responseStatusCode)));
}
errors = list;
}
if (httpResponse.IsSuccessStatusCode || httpResponse.StatusCode == HttpStatusCode.NotFound)
{
try
{
string text = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false);
string newone = await Task.Run(() =>
newone = text
);
content = _serializer.Deserialize(text);
await Task.Run(() => _cachingProvider.SetCacheAsString(cacheKey, text));
if (_logger.IsEnabled(LogLevel.Debug))
{
object arg = JsonConvert.DeserializeObject(text);
_logger.LogDebug($"Layout Service Response JSON : {arg}");
}
}
catch (Exception innerException)
{
errors = AddError(errors, new InvalidResponseSitecoreLayoutServiceClientException(innerException), responseStatusCode);
}
}
try
{
metadata = httpResponse.Headers.SelectMany((KeyValuePair<string, IEnumerable<string>> x) => x.Value.Select((string y) => new
{
Key = x.Key,
Value = y
})).ToLookup(k => k.Key, v => v.Value);
}
catch (Exception innerException2)
{
errors = AddError(errors, new InvalidResponseSitecoreLayoutServiceClientException(innerException2), responseStatusCode);
}
}
catch (Exception innerException3)
{
errors.Add(new CouldNotContactSitecoreLayoutServiceClientException(innerException3));
}
timer.Stop();
_logger.LogDebug($"Total Execution Time : {timer.ElapsedMilliseconds}");
return new SitecoreLayoutResponse(request, errors)
{
Content = content,
Metadata = metadata
};
}
protected virtual HttpRequestMessage BuildMessage(SitecoreLayoutRequest request, HttpLayoutRequestHandlerOptions options)
{
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, _client.BaseAddress);
if (options != null)
{
foreach (Action<SitecoreLayoutRequest, HttpRequestMessage> item in options.RequestMap)
{
item(request, httpRequestMessage);
}
return httpRequestMessage;
}
return httpRequestMessage;
}
protected virtual async Task<HttpResponseMessage> GetResponseAsync(HttpRequestMessage message)
{
return await _client.SendAsync(message).ConfigureAwait(continueOnCapturedContext: false);
}
private static List<SitecoreLayoutServiceClientException> AddError(List<SitecoreLayoutServiceClientException> errors, SitecoreLayoutServiceClientException error, int statusCode = 0)
{
if (statusCode > 0)
{
error.Data.Add("HttpStatusCode_KeyName", statusCode);
}
errors.Add(error);
return errors;
}
private SitecoreLayoutRequestOptions MergeLayoutRequestOptions(string handlerName)
{
SitecoreLayoutRequestOptions value = _layoutRequestOptions.Value;
SitecoreLayoutRequestOptions sitecoreLayoutRequestOptions = _layoutRequestOptions.Get(handlerName);
if (AreEqual(value.RequestDefaults, sitecoreLayoutRequestOptions.RequestDefaults))
{
return value;
}
SitecoreLayoutRequestOptions sitecoreLayoutRequestOptions2 = value;
SitecoreLayoutRequest requestDefaults = value.RequestDefaults;
SitecoreLayoutRequest requestDefaults2 = sitecoreLayoutRequestOptions.RequestDefaults;
foreach (KeyValuePair<string, object> item in requestDefaults2)
{
if (requestDefaults.ContainsKey(item.Key))
{
requestDefaults[item.Key] = requestDefaults2[item.Key];
}
else
{
requestDefaults.Add(item.Key, requestDefaults2[item.Key]);
}
}
sitecoreLayoutRequestOptions2.RequestDefaults = requestDefaults;
return sitecoreLayoutRequestOptions2;
}
private static bool AreEqual(IDictionary<string, object?> dictionary1, IDictionary<string, object?> dictionary2)
{
if (dictionary1.Count != dictionary2.Count)
{
return false;
}
foreach (string key in dictionary1.Keys)
{
if (!dictionary2.TryGetValue(key, out var value) || dictionary1[key] != value)
{
return false;
}
}
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment