Skip to content

Commit c3ece1c

Browse files
committed
add Idempotency
1 parent afe44d8 commit c3ece1c

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed
Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,23 @@
1-
using Microsoft.AspNetCore.Http;
2-
using System;
3-
using System.Threading.Tasks;
1+
namespace RideSharingApp.Api.Middlewares;
42

5-
namespace RideSharingApp.Api.Middlewares
3+
public class CorrelationIdMiddleware
64
{
7-
public class CorrelationIdMiddleware
5+
private const string CorrelationIdHeader = "X-Correlation-Id";
6+
private readonly RequestDelegate _next;
7+
8+
public CorrelationIdMiddleware(RequestDelegate next)
89
{
9-
private const string CorrelationIdHeader = "X-Correlation-Id";
10-
private readonly RequestDelegate _next;
10+
_next = next;
11+
}
1112

12-
public CorrelationIdMiddleware(RequestDelegate next)
13+
public Task InvokeAsync(HttpContext context)
14+
{
15+
if (!context.Request.Headers.ContainsKey(CorrelationIdHeader))
1316
{
14-
_next = next;
17+
context.Request.Headers[CorrelationIdHeader] = Guid.NewGuid().ToString();
1518
}
1619

17-
public async Task InvokeAsync(HttpContext context)
18-
{
19-
if (!context.Request.Headers.ContainsKey(CorrelationIdHeader))
20-
{
21-
context.Request.Headers[CorrelationIdHeader] = Guid.NewGuid().ToString();
22-
}
23-
context.Response.Headers[CorrelationIdHeader] = context.Request.Headers[CorrelationIdHeader];
24-
await _next(context);
25-
}
20+
context.Response.Headers[CorrelationIdHeader] = context.Request.Headers[CorrelationIdHeader];
21+
return _next(context);
2622
}
2723
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System.Collections.Concurrent;
2+
3+
namespace RideSharingApp.Api.Middlewares;
4+
5+
public class IdempotencyMiddleware
6+
{
7+
private readonly RequestDelegate _next;
8+
private static readonly ConcurrentDictionary<string, string> _responses = new();
9+
10+
public IdempotencyMiddleware(RequestDelegate next)
11+
{
12+
_next = next;
13+
}
14+
15+
public async Task InvokeAsync(HttpContext context)
16+
{
17+
if (context.Request.Method != HttpMethods.Post)
18+
{
19+
await _next(context);
20+
return;
21+
}
22+
23+
if (!context.Request.Headers.TryGetValue("Idempotency-Key", out var key))
24+
{
25+
context.Response.StatusCode = StatusCodes.Status400BadRequest;
26+
await context.Response.WriteAsync("Missing Idempotency-Key header");
27+
return;
28+
}
29+
30+
if (_responses.TryGetValue(key!, out var cachedResponse))
31+
{
32+
context.Response.ContentType = "application/json";
33+
await context.Response.WriteAsync(cachedResponse);
34+
return;
35+
}
36+
37+
var originalBodyStream = context.Response.Body;
38+
await using var memoryStream = new MemoryStream();
39+
context.Response.Body = memoryStream;
40+
41+
await _next(context);
42+
43+
memoryStream.Position = 0;
44+
var responseText = await new StreamReader(memoryStream).ReadToEndAsync();
45+
46+
if (context.Response.StatusCode is >= 200 and < 300)
47+
{
48+
_responses[key!] = responseText;
49+
}
50+
51+
memoryStream.Position = 0;
52+
await memoryStream.CopyToAsync(originalBodyStream);
53+
context.Response.Body = originalBodyStream;
54+
}
55+
}

0 commit comments

Comments
 (0)