49 lines
1.4 KiB
C#
49 lines
1.4 KiB
C#
using ClaudeMailbox.Data.Repositories;
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
namespace ClaudeMailbox.Http;
|
|
|
|
public sealed class MailboxHeaderMiddleware
|
|
{
|
|
public const string HeaderName = "X-Mailbox";
|
|
public const string ItemsKey = "Mailbox";
|
|
|
|
private readonly RequestDelegate _next;
|
|
|
|
public MailboxHeaderMiddleware(RequestDelegate next) => _next = next;
|
|
|
|
public async Task InvokeAsync(HttpContext ctx, MailboxRepository mailboxes)
|
|
{
|
|
// Health is always anonymous.
|
|
if (ctx.Request.Path.StartsWithSegments("/health"))
|
|
{
|
|
await _next(ctx);
|
|
return;
|
|
}
|
|
|
|
var name = ctx.Request.Headers[HeaderName].ToString().Trim();
|
|
|
|
// These endpoints work without identity (discovery / read-only status).
|
|
var path = ctx.Request.Path;
|
|
var isAnonymous =
|
|
path.Equals("/v1/list", StringComparison.OrdinalIgnoreCase) ||
|
|
path.Equals("/v1/peek", StringComparison.OrdinalIgnoreCase);
|
|
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
{
|
|
if (isAnonymous)
|
|
{
|
|
await _next(ctx);
|
|
return;
|
|
}
|
|
ctx.Response.StatusCode = 400;
|
|
await ctx.Response.WriteAsync($"Missing {HeaderName} header.");
|
|
return;
|
|
}
|
|
|
|
ctx.Items[ItemsKey] = name;
|
|
await mailboxes.UpsertAsync(name, ctx.RequestAborted);
|
|
await _next(ctx);
|
|
}
|
|
}
|