diff --git a/CHANGELOG.md b/CHANGELOG.md index e87dee655..d15974d0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,15 @@ et négociation HTTP/3 côté client PostIt. désactivé (grisé) et inerte au clic. Corrigé en `$parent[ContentPage].((vm:XxxViewModel)DataContext).Cmd` (syntaxe déjà en vigueur dans `CirclesPage` / `EstimateListPage`). +* [Yavsc.Blogs] La suppression d'un fichier (`DELETE api/v1/fs/{name}`) + renvoyait un 40x alors que le fichier était bien supprimé du disque. + `DeleteUserDirOrFile` (et `DeleteUserFile`) lisaient + `FileInfo.Length` **après** `fi.Delete()` ; or `FileInfo.Length` + lève `FileNotFoundException` une fois le fichier disparu — le `catch` + du contrôleur transformait cette exception en 400, d'où le message + perçu « le fichier n'existe pas sur le serveur » tandis que la + suppression avait réussi. La taille est désormais capturée avant la + suppression. ## [1.0.8-rc17] - unstable diff --git a/src/Yavsc.Blogs.Tests/FileSystemApiTests.cs b/src/Yavsc.Blogs.Tests/FileSystemApiTests.cs index e67f235aa..0e36a6018 100644 --- a/src/Yavsc.Blogs.Tests/FileSystemApiTests.cs +++ b/src/Yavsc.Blogs.Tests/FileSystemApiTests.cs @@ -363,4 +363,35 @@ public sealed class FileSystemApiTests : IClassFixture Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } + + /// + /// Regression for the "delete returns 40x yet the file is gone" + /// report: DeleteUserDirOrFile read FileInfo.Length + /// after fi.Delete(), and FileInfo.Length + /// throws FileNotFoundException once the file no longer + /// exists. The controller's catch turned that into a 400 + /// even though the file had already been removed — the user saw + /// "le fichier n'existe pas sur le serveur" while the delete in + /// fact succeeded. This test asserts a clean 200 and that the + /// file is gone from disk. + /// + [Fact] + public async Task Delete_fs_removes_the_file_and_returns_200() + { + _fixture.ResetDatabase(); + _fixture.SeedUser("alice"); + + var bytes = System.Text.Encoding.UTF8.GetBytes("delete me"); + WritePhysicalFile(_fixture, "alice", "doomed.txt", bytes); + + using var http = NewClient("alice"); + var response = await http.DeleteAsync( + "/api/v1/fs/doomed.txt", TestContext.Current.CancellationToken); + var body = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); + + Assert.True(response.StatusCode == HttpStatusCode.OK, + $"Expected 200, got {(int)response.StatusCode} ({response.StatusCode}): {body}"); + Assert.False(File.Exists(PhysicalFile(_fixture, "alice", "doomed.txt")), + "The file must be gone from disk after a successful delete."); + } } \ No newline at end of file diff --git a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs index 762c18f36..e0d5b8b9d 100644 --- a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs +++ b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs @@ -70,8 +70,12 @@ namespace Yavsc.Server.Helpers var root = Path.Combine(siteSettings.Blog, user.UserName); var fi = new FileInfo(Path.Combine(root, fileName)); if (!fi.Exists) return; + // Capture the length BEFORE deleting: FileInfo.Length throws + // FileNotFoundException once the file is gone, which would + // surface as a 400 even though the delete already succeeded. + var length = fi.Length; fi.Delete(); - user.DiskUsage -= fi.Length; + user.DiskUsage -= length; } public static FsOperationInfo DeleteUserDirOrFile(this ApplicationUser user, string dirName, SiteSettings siteSettings) @@ -85,8 +89,15 @@ namespace Yavsc.Server.Helpers { var fi = new FileInfo(Path.Combine(root, dirName)); if (!fi.Exists) return new FsOperationInfo { Done = false, ErrorCode = ErrorCode.NotFound, ErrorMessage = "non existent" }; + // Capture the length BEFORE deleting: FileInfo.Length + // throws FileNotFoundException once the file is gone, so + // reading it after fi.Delete() would throw — the caller's + // catch turns that into a 400 even though the file was + // already removed (the user sees "file does not exist" + // while the delete in fact succeeded). + var length = fi.Length; fi.Delete(); - user.DiskUsage -= fi.Length; + user.DiskUsage -= length; } else {