Skip to content

Commit

Permalink
Added requestLogger that can be toggled using feature flag (#307)
Browse files Browse the repository at this point in the history
  • Loading branch information
TTA777 authored Dec 4, 2024
1 parent ac8ffc7 commit af08e5d
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 6 deletions.
4 changes: 4 additions & 0 deletions coffeecard/CoffeeCard.Library/Utils/FeatureFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ public class FeatureFlags
/// Controls whether the API should manage the registration to the MobilePayWebhooks API at startup. Disabling this feature flag, assumes that the Webhook Registration is handled outside of the Analog Core API.
/// </summary>
public const string MobilePayManageWebhookRegistration = "MobilePayManageWebhookRegistration";
/// <summary>
/// Controls whether the RequestLoggerMiddleware is added to the pipeline
/// </summary>
public const string RequestLoggerEnabled = "RequestLoggerEnabled";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Serilog;

namespace CoffeeCard.WebApi.Controllers.v2
Expand All @@ -25,16 +26,18 @@ public class MobilePayController : ControllerBase
private readonly IPurchaseService _purchaseService;
private readonly MobilePaySettingsV2 _mobilePaySettings;
private readonly IWebhookService _webhookService;
private readonly ILogger<MobilePayController> _logger;

/// <summary>
/// Initializes a new instance of the <see cref="MobilePayController"/> class.
/// </summary>
public MobilePayController(IPurchaseService purchaseService, IWebhookService webhookService,
MobilePaySettingsV2 mobilePaySettings)
MobilePaySettingsV2 mobilePaySettings, ILogger<MobilePayController> logger)
{
_purchaseService = purchaseService;
_webhookService = webhookService;
_mobilePaySettings = mobilePaySettings;
_logger = logger;
}

/// <summary>
Expand Down Expand Up @@ -82,15 +85,15 @@ private async Task<bool> VerifySignature(string mpSignatureHeader)
rawRequestBody = await stream.ReadToEndAsync();
}

Log.Debug("Raw request body (trimmed): '{Body}'", rawRequestBody.Trim());
Log.Debug("Endpoint Url '{EndpointUrl}', SignatureKey '{Signature}'", endpointUrl, signatureKey);
_logger.LogDebug("Raw request body (trimmed): '{Body}'", rawRequestBody.Trim());
_logger.LogDebug("Endpoint Url '{EndpointUrl}', SignatureKey '{Signature}'", endpointUrl, signatureKey);

var hash = new HMACSHA1(Encoding.UTF8.GetBytes(signatureKey))
.ComputeHash(Encoding.UTF8.GetBytes(endpointUrl + rawRequestBody.Trim()));
var computedSignature = Convert.ToBase64String(hash);

Log.Debug("ComputedSignature: {Signature}", computedSignature);
Log.Debug("mpSignatureHeader {mpSignatureHeader}", mpSignatureHeader);
_logger.LogDebug("ComputedSignature: {Signature}", computedSignature);
_logger.LogDebug("mpSignatureHeader {mpSignatureHeader}", mpSignatureHeader);

return mpSignatureHeader.Equals(computedSignature);
}
Expand Down
88 changes: 88 additions & 0 deletions coffeecard/CoffeeCard.WebApi/Helpers/RequestLoggerMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace CoffeeCard.WebApi.Helpers;

public class RequestLoggerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<RequestLoggerMiddleware> _logger;

public RequestLoggerMiddleware(RequestDelegate next, ILogger<RequestLoggerMiddleware> logger)
{
_next = next;
_logger = logger;
}

public async Task InvokeAsync(HttpContext context)
{
// Log the Request
var request = await FormatRequest(context.Request);
_logger.LogDebug("Incoming Request: {Request}", request);

// Copy original response body stream
var originalResponseBodyStream = context.Response.Body;

using (var responseBody = new MemoryStream())
{
context.Response.Body = responseBody;

// Call the next middleware in the pipeline
await _next(context);

// Log the Response
var response = await FormatResponse(context.Response);
_logger.LogDebug("Outgoing Response: {Response}", response);

// Copy the response body back to the original stream
await responseBody.CopyToAsync(originalResponseBodyStream);
}
}

private async Task<string> FormatRequest(HttpRequest request)
{
request.EnableBuffering();

var bodyAsText = string.Empty;
if (request.Body.CanSeek)
{
request.Body.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(request.Body, Encoding.UTF8, leaveOpen: true))
{
bodyAsText = await reader.ReadToEndAsync();
}

request.Body.Seek(0, SeekOrigin.Begin);
}

var headers = FormatHeaders(request.Headers);

return
$"Method: {request.Method}, Path: {request.Path}, QueryString: {request.QueryString}, Headers: {headers}, Body: {bodyAsText}";
}

private async Task<string> FormatResponse(HttpResponse response)
{
response.Body.Seek(0, SeekOrigin.Begin);
var text = await new StreamReader(response.Body).ReadToEndAsync();
response.Body.Seek(0, SeekOrigin.Begin);

return $"StatusCode: {response.StatusCode}, Body: {text}";
}

private string FormatHeaders(IHeaderDictionary headers)
{
var formattedHeaders = new StringBuilder();

foreach (KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues> header in headers)
{
formattedHeaders.AppendLine($"{header.Key}: {header.Value}");
}

return formattedHeaders.ToString().TrimEnd();
}
}
7 changes: 7 additions & 0 deletions coffeecard/CoffeeCard.WebApi/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,13 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVers
app.UseStaticFiles();

app.UseRouting();
var featureManager = app.ApplicationServices.GetRequiredService<IFeatureManager>();

var isRequestLoggerEnabled = featureManager.IsEnabledAsync(FeatureFlags.RequestLoggerEnabled).Result;
if (isRequestLoggerEnabled)
{
app.UseMiddleware<RequestLoggerMiddleware>();
}

app.UseCors();

Expand Down
3 changes: 2 additions & 1 deletion coffeecard/CoffeeCard.WebApi/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId", "WithExceptionDetails" ]
},
"FeatureManagement": {
"MobilePayManageWebhookRegistration": false
"MobilePayManageWebhookRegistration": false,
"RequestLoggerEnabled": false
}
}

0 comments on commit af08e5d

Please sign in to comment.