Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public async Task Production_does_not_map_ui_endpoints_by_default()
var comparePageResponse = await app.Client.GetAsync($"/compare?localTraceId={app.SingleEntry.Id}");
var scriptResponse = await app.Client.GetAsync("/debug/js/debugprobe-ui.js");
var logoResponse = await app.Client.GetAsync("/debug/logo.png");
var environmentResponse = await app.Client.GetAsync("/debug/environment");
var jsonResponse = await app.Client.GetAsync($"/debug/json/{app.SingleEntry.Id}");
var clearResponse = await app.Client.PostAsync("/debug/clear", null);

Assert.Equal(HttpStatusCode.OK, capturedResponse.StatusCode);
Expand All @@ -26,6 +28,8 @@ public async Task Production_does_not_map_ui_endpoints_by_default()
Assert.Equal(HttpStatusCode.NotFound, scriptResponse.StatusCode);
Assert.Equal(HttpStatusCode.NotFound, logoResponse.StatusCode);
Assert.Equal(HttpStatusCode.NotFound, clearResponse.StatusCode);
Assert.Equal(HttpStatusCode.NotFound, environmentResponse.StatusCode);
Assert.Equal(HttpStatusCode.NotFound, jsonResponse.StatusCode);
}

[Fact]
Expand All @@ -43,6 +47,8 @@ public async Task Production_maps_ui_endpoints_when_explicitly_allowed()
var comparePageResponse = await app.Client.GetAsync($"/compare?localTraceId={app.SingleEntry.Id}");
var scriptResponse = await app.Client.GetAsync("/debug/js/debugprobe-ui.js");
var logoResponse = await app.Client.GetAsync("/debug/logo.png");
var environmentResponse = await app.Client.GetAsync("/debug/environment");
var jsonResponse = await app.Client.GetAsync($"/debug/json/{app.SingleEntry.Id}");
var clearResponse = await app.Client.PostAsync("/debug/clear", null);

Assert.Equal(HttpStatusCode.OK, debugResponse.StatusCode);
Expand All @@ -51,10 +57,12 @@ public async Task Production_maps_ui_endpoints_when_explicitly_allowed()
Assert.Equal(HttpStatusCode.OK, scriptResponse.StatusCode);
Assert.Equal(HttpStatusCode.OK, logoResponse.StatusCode);
Assert.Equal(HttpStatusCode.OK, clearResponse.StatusCode);
Assert.Equal(HttpStatusCode.OK, environmentResponse.StatusCode);
Assert.Equal(HttpStatusCode.OK, jsonResponse.StatusCode);
}

[Fact]
public async Task Production_keeps_machine_readable_debug_endpoints_available_by_default()
public async Task Production_blocks_machine_readable_endpoints_by_default()
{
await using var app = await DebugProbeWebApplication.CreateAsync(
Environments.Production,
Expand All @@ -64,8 +72,11 @@ public async Task Production_keeps_machine_readable_debug_endpoints_available_by

var environmentResponse = await app.Client.GetAsync("/debug/environment");
var jsonResponse = await app.Client.GetAsync($"/debug/json/{app.SingleEntry.Id}");
var compareResponse = await app.Client.GetAsync(
$"/debug/compare/{app.SingleEntry.Id}?baseUrl=http://localhost&remoteTraceId={Guid.NewGuid()}");

Assert.Equal(HttpStatusCode.OK, environmentResponse.StatusCode);
Assert.Equal(HttpStatusCode.OK, jsonResponse.StatusCode);
Assert.Equal(HttpStatusCode.NotFound, environmentResponse.StatusCode);
Assert.Equal(HttpStatusCode.NotFound, jsonResponse.StatusCode);
Assert.Equal(HttpStatusCode.NotFound, compareResponse.StatusCode);
}
}
142 changes: 71 additions & 71 deletions DebugProbe.AspNetCore/Extensions/DebugProbeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,100 +167,100 @@ public static IApplicationBuilder UseDebugProbe(this IApplicationBuilder app, Ac
RequireDebugAuthorization(webApp.Map($"{prefix}/favicon.ico", ctx =>
EmbeddedAssetWriter.WriteEmbeddedAsset(ctx, "DebugProbe.AspNetCore.Assets.images.debugprobe_favicon.ico", "image/x-icon")
).ExcludeFromDescription(), options);
}

RequireDebugAuthorization(webApp.MapGet($"{prefix}/compare/{{id}}", async (string id, string baseUrl, string remoteTraceId,
DebugEntryStore store,
DebugProbeOptions options) =>
{
var localEnvironment = store.Environment;
var localEntry = store.Get(id);

if (localEntry is null)
RequireDebugAuthorization(webApp.MapGet($"{prefix}/compare/{{id}}", async (string id, string baseUrl, string remoteTraceId,
DebugEntryStore store,
DebugProbeOptions options) =>
{
return Results.NotFound("Local trace not found");
}
var localEnvironment = store.Environment;
var localEntry = store.Get(id);

if (!Guid.TryParse(remoteTraceId, out _))
{
return Results.BadRequest("Invalid remote trace id");
}
if (localEntry is null)
{
return Results.NotFound("Local trace not found");
}

var validation = await CompareUrlValidator.ValidateCompareBaseUrlAsync(baseUrl, options);
if (!Guid.TryParse(remoteTraceId, out _))
{
return Results.BadRequest("Invalid remote trace id");
}

if (!validation.IsValid)
{
return Results.BadRequest(validation.Error);
}
var validation = await CompareUrlValidator.ValidateCompareBaseUrlAsync(baseUrl, options);

var remoteEnvironmentUrl = new Uri(validation.BaseUri!, $"{prefix}/environment");
if (!validation.IsValid)
{
return Results.BadRequest(validation.Error);
}

var remoteEntryUrl = new Uri(validation.BaseUri!, $"{prefix}/json/{remoteTraceId}");
var remoteEnvironmentUrl = new Uri(validation.BaseUri!, $"{prefix}/environment");

DebugEntry? remoteEntry;
DebugEnvironment? remoteEnvironment;
var remoteEntryUrl = new Uri(validation.BaseUri!, $"{prefix}/json/{remoteTraceId}");

try
{
remoteEnvironment = await Http.GetFromJsonAsync<DebugEnvironment>(remoteEnvironmentUrl);
DebugEntry? remoteEntry;
DebugEnvironment? remoteEnvironment;

if (remoteEnvironment is null)
try
{
return Results.BadRequest("Failed to load remote environment");
}
remoteEnvironment = await Http.GetFromJsonAsync<DebugEnvironment>(remoteEnvironmentUrl);

if (remoteEnvironment is null)
{
return Results.BadRequest("Failed to load remote environment");
}

remoteEntry = await Http.GetFromJsonAsync<DebugEntry>(remoteEntryUrl);
remoteEntry = await Http.GetFromJsonAsync<DebugEntry>(remoteEntryUrl);

if (remoteEntry is null)
if (remoteEntry is null)
{
return Results.NotFound("Remote trace not found");
}
}
catch
{
return Results.NotFound("Remote trace not found");
return Results.BadRequest("Failed to reach remote server");
}
}
catch
{
return Results.BadRequest("Failed to reach remote server");
}

var diff = DebugEntryComparer.Compare(localEntry, remoteEntry);

var diff = DebugEntryComparer.Compare(localEntry, remoteEntry);

return Results.Ok(new
{
localTrace = localEntry,
remoteTrace = remoteEntry,
localEnvironment,
remoteEnvironment,
method = new { local = localEntry.Method, remote = remoteEntry.Method },
path = new { local = localEntry.Path, remote = remoteEntry.Path },
status = new { local = localEntry.StatusCode, remote = remoteEntry.StatusCode },

requestTime = new
return Results.Ok(new
{
local = localEntry.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"),
remote = remoteEntry.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"),
},

environment = new { local = localEnvironment.Environment, remote = remoteEnvironment?.Environment ?? "" },
culture = new { local = localEnvironment.Culture, remote = remoteEnvironment?.Culture ?? "" },
requestBody = new { local = localEntry.RequestBody ?? "", remote = remoteEntry.RequestBody ?? "" },
responseBody = new { local = localEntry.ResponseBody ?? "", remote = remoteEntry.ResponseBody ?? "" },
diffs = diff
});
localTrace = localEntry,
remoteTrace = remoteEntry,
localEnvironment,
remoteEnvironment,
method = new { local = localEntry.Method, remote = remoteEntry.Method },
path = new { local = localEntry.Path, remote = remoteEntry.Path },
status = new { local = localEntry.StatusCode, remote = remoteEntry.StatusCode },

requestTime = new
{
local = localEntry.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"),
remote = remoteEntry.RequestTimeUtc.ToLocalTime().ToString("HH:mm:ss"),
},

environment = new { local = localEnvironment.Environment, remote = remoteEnvironment?.Environment ?? "" },
culture = new { local = localEnvironment.Culture, remote = remoteEnvironment?.Culture ?? "" },
requestBody = new { local = localEntry.RequestBody ?? "", remote = remoteEntry.RequestBody ?? "" },
responseBody = new { local = localEntry.ResponseBody ?? "", remote = remoteEntry.ResponseBody ?? "" },
diffs = diff
});

}).ExcludeFromDescription(), options);
}).ExcludeFromDescription(), options);

RequireDebugAuthorization(webApp.MapGet($"{prefix}/environment", (DebugEntryStore store) =>
{
return Results.Ok(store.Environment);
RequireDebugAuthorization(webApp.MapGet($"{prefix}/environment", (DebugEntryStore store) =>
{
return Results.Ok(store.Environment);

}).ExcludeFromDescription(), options);
}).ExcludeFromDescription(), options);

RequireDebugAuthorization(webApp.MapGet($"{prefix}/json/{{id}}", (string id, DebugEntryStore store) =>
{
var item = store.Get(id);
RequireDebugAuthorization(webApp.MapGet($"{prefix}/json/{{id}}", (string id, DebugEntryStore store) =>
{
var item = store.Get(id);

return item is null ? Results.NotFound() : Results.Json(item);
return item is null ? Results.NotFound() : Results.Json(item);

}).ExcludeFromDescription(), options);
}).ExcludeFromDescription(), options);
}


}
Expand Down
Loading