From 71ff464791044afad182aa51fd0b9f68ebeb2d21 Mon Sep 17 00:00:00 2001 From: Duco Date: Tue, 20 Jun 2023 22:16:11 +0200 Subject: [PATCH 01/41] Added MimeService --- src/HttPlaceholder.Common/IMimeService.cs | 14 ++++++++++++++ .../HttPlaceholder.Infrastructure.csproj | 4 ++++ .../Implementations/MimeService.cs | 11 +++++++++++ 3 files changed, 29 insertions(+) create mode 100644 src/HttPlaceholder.Common/IMimeService.cs create mode 100644 src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs diff --git a/src/HttPlaceholder.Common/IMimeService.cs b/src/HttPlaceholder.Common/IMimeService.cs new file mode 100644 index 000000000..e4dc79d23 --- /dev/null +++ b/src/HttPlaceholder.Common/IMimeService.cs @@ -0,0 +1,14 @@ +namespace HttPlaceholder.Common; + +/// +/// Describes a class that is used to convert between file extensions and mime types. +/// +public interface IMimeService +{ + /// + /// Converts a given input to a MIME type. + /// + /// The input (can be file path, file name or just plain extension). + /// The MIME type. + string GetMimeType(string input); +} diff --git a/src/HttPlaceholder.Infrastructure/HttPlaceholder.Infrastructure.csproj b/src/HttPlaceholder.Infrastructure/HttPlaceholder.Infrastructure.csproj index 3708e3898..12792c0aa 100644 --- a/src/HttPlaceholder.Infrastructure/HttPlaceholder.Infrastructure.csproj +++ b/src/HttPlaceholder.Infrastructure/HttPlaceholder.Infrastructure.csproj @@ -9,6 +9,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs b/src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs new file mode 100644 index 000000000..a5fd48708 --- /dev/null +++ b/src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs @@ -0,0 +1,11 @@ +using HttPlaceholder.Application.Infrastructure.DependencyInjection; +using HttPlaceholder.Common; + +namespace HttPlaceholder.Infrastructure.Implementations; + +/// +public class MimeService : IMimeService, ISingletonService +{ + /// + public string GetMimeType(string input) => MimeTypes.GetMimeType("awesome-file.json"); +} From 1b83d743a81eb7460a8f18f2c7dc9a5b1c14b97a Mon Sep 17 00:00:00 2001 From: Duco Date: Wed, 21 Jun 2023 19:28:16 +0200 Subject: [PATCH 02/41] Added tests for MimeService --- .../Implementations/MimeServiceFacts.cs | 25 +++++++++++++++++++ .../Implementations/MimeService.cs | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs diff --git a/src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs b/src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs new file mode 100644 index 000000000..368ca6b4a --- /dev/null +++ b/src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs @@ -0,0 +1,25 @@ +using HttPlaceholder.Infrastructure.Implementations; + +namespace HttPlaceholder.Infrastructure.Tests.Implementations; + +[TestClass] +public class MimeServiceFacts +{ + private readonly MimeService _mimeService = new(); + + [DataTestMethod] + [DataRow(".jpg", "image/jpeg")] + [DataRow(".jpeg", "image/jpeg")] + [DataRow("/path/somefile.jpeg", "image/jpeg")] + [DataRow("file.bin", "application/octet-stream")] + [DataRow("jpeg", "application/octet-stream")] + [DataRow("file.json", "application/json")] + public void GetMimeType_HappyFlow(string input, string expectedOutput) + { + // Act + var result = _mimeService.GetMimeType(input); + + // Assert + Assert.AreEqual(expectedOutput, result); + } +} diff --git a/src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs b/src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs index a5fd48708..de5e11f2a 100644 --- a/src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs +++ b/src/HttPlaceholder.Infrastructure/Implementations/MimeService.cs @@ -7,5 +7,5 @@ namespace HttPlaceholder.Infrastructure.Implementations; public class MimeService : IMimeService, ISingletonService { /// - public string GetMimeType(string input) => MimeTypes.GetMimeType("awesome-file.json"); + public string GetMimeType(string input) => MimeTypes.GetMimeType(input); } From 5930e01f9ce5e725199485b51e77b29b13cf35f4 Mon Sep 17 00:00:00 2001 From: Duco Date: Wed, 21 Jun 2023 19:39:02 +0200 Subject: [PATCH 03/41] Updated unit test --- .../ResponseWriters/FileResponseWriterFacts.cs | 8 ++++++++ .../StubExecution/ResponseWriters/FileResponseWriter.cs | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/HttPlaceholder.Application.Tests/StubExecution/ResponseWriters/FileResponseWriterFacts.cs b/src/HttPlaceholder.Application.Tests/StubExecution/ResponseWriters/FileResponseWriterFacts.cs index 663017d8f..7d43ef946 100644 --- a/src/HttPlaceholder.Application.Tests/StubExecution/ResponseWriters/FileResponseWriterFacts.cs +++ b/src/HttPlaceholder.Application.Tests/StubExecution/ResponseWriters/FileResponseWriterFacts.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Linq; using HttPlaceholder.Application.Configuration; using HttPlaceholder.Application.Interfaces.Persistence; using HttPlaceholder.Application.StubExecution.ResponseWriters; @@ -93,6 +94,7 @@ public async Task FileResponseWriter_WriteToResponseAsync_HappyFlow_FileFoundDir // Arrange _settings.Stub.AllowGlobalFileSearch = true; var fileServiceMock = _mocker.GetMock(); + var mimeServiceMock = _mocker.GetMock(); var writer = _mocker.CreateInstance(); var body = new byte[] {1, 2, 3}; @@ -117,6 +119,11 @@ public async Task FileResponseWriter_WriteToResponseAsync_HappyFlow_FileFoundDir .Setup(m => m.ReadAllBytesAsync(path, It.IsAny())) .ReturnsAsync(body); + const string mime = "image/png"; + mimeServiceMock + .Setup(m => m.GetMimeType(path)) + .Returns(mime); + // Act var result = await writer.WriteToResponseAsync(stub, response, CancellationToken.None); @@ -124,6 +131,7 @@ public async Task FileResponseWriter_WriteToResponseAsync_HappyFlow_FileFoundDir Assert.IsTrue(result.Executed); Assert.AreEqual(body, response.Body); Assert.AreEqual(response.BodyIsBinary, !textFile); + Assert.AreEqual(mime, response.Headers.Single(h => h.Key == "Content-Type").Value); } [DataTestMethod] diff --git a/src/HttPlaceholder.Application/StubExecution/ResponseWriters/FileResponseWriter.cs b/src/HttPlaceholder.Application/StubExecution/ResponseWriters/FileResponseWriter.cs index 4c9f0e1c4..8e41a419d 100644 --- a/src/HttPlaceholder.Application/StubExecution/ResponseWriters/FileResponseWriter.cs +++ b/src/HttPlaceholder.Application/StubExecution/ResponseWriters/FileResponseWriter.cs @@ -22,17 +22,20 @@ internal class FileResponseWriter : IResponseWriter, ISingletonService private readonly ILogger _logger; private readonly IOptionsMonitor _options; private readonly IStubRootPathResolver _stubRootPathResolver; + private readonly IMimeService _mimeService; public FileResponseWriter( IFileService fileService, IStubRootPathResolver stubRootPathResolver, IOptionsMonitor options, - ILogger logger) + ILogger logger, + IMimeService mimeService) { _fileService = fileService; _stubRootPathResolver = stubRootPathResolver; _options = options; _logger = logger; + _mimeService = mimeService; } /// @@ -85,6 +88,7 @@ public async Task WriteToResponseAsync(StubModel return StubResponseWriterResultModel.IsNotExecuted(GetType().Name); } + response.Headers.AddOrReplaceCaseInsensitive(HeaderKeys.ContentType, _mimeService.GetMimeType(finalFilePath)); response.Body = await _fileService.ReadAllBytesAsync(finalFilePath, cancellationToken); response.BodyIsBinary = string.IsNullOrWhiteSpace(stub.Response.TextFile); return StubResponseWriterResultModel.IsExecuted(GetType().Name); From 7e2bc6d4a1e245efe22e050bbc09e94ceb50647a Mon Sep 17 00:00:00 2001 From: Duco Date: Wed, 21 Jun 2023 19:41:18 +0200 Subject: [PATCH 04/41] Updated sample --- docs/samples/05-base64-file.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/samples/05-base64-file.yml b/docs/samples/05-base64-file.yml index 5b46d8f3e..e1f32cd99 100644 --- a/docs/samples/05-base64-file.yml +++ b/docs/samples/05-base64-file.yml @@ -10,8 +10,6 @@ response: statusCode: 200 file: cat_file.jpg - headers: - Content-Type: image/jpeg # A simple GET request script that contains a base64 encoded string (this can for example be a binary). In this case, just go to http://localhost:{port}/cat.jpg - id: image-base64 From 4b240ac028e6e9ca941c2abe5618d7b5f123a03e Mon Sep 17 00:00:00 2001 From: Duco Date: Wed, 21 Jun 2023 19:43:39 +0200 Subject: [PATCH 05/41] Updated changelog --- CHANGELOG | 1 + .../Implementations/MimeServiceFacts.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index fc8c09d49..a9262333d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ - Added string / regex replacement response writer (https://github.com/dukeofharen/httplaceholder/pull/309). - Added SignalR connection for stubs (https://github.com/dukeofharen/httplaceholder/pull/310). - When generating a stub based on a request, also take the saved saved response (if there is one) into account (https://github.com/dukeofharen/httplaceholder/pull/311). +- When using the file response writer and no specific content type is set; determine the content type based on the file extension (https://github.com/dukeofharen/httplaceholder/pull/312). [2023.4.25] - Upgraded to .NET 7 (https://github.com/dukeofharen/httplaceholder/pull/293). diff --git a/src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs b/src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs index 368ca6b4a..6d6dc4158 100644 --- a/src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs +++ b/src/HttPlaceholder.Infrastructure.Tests/Implementations/MimeServiceFacts.cs @@ -14,6 +14,7 @@ public class MimeServiceFacts [DataRow("file.bin", "application/octet-stream")] [DataRow("jpeg", "application/octet-stream")] [DataRow("file.json", "application/json")] + [DataRow("FILE.JSON", "application/json")] public void GetMimeType_HappyFlow(string input, string expectedOutput) { // Act From 02c6f3063aa77a3a3f188c7ecc5d73aafb840ed8 Mon Sep 17 00:00:00 2001 From: Duco Date: Wed, 21 Jun 2023 20:28:14 +0200 Subject: [PATCH 06/41] Updated integration tests --- .../Integration/Stubs/StubFileIntegrationTests.cs | 6 +++++- src/HttPlaceholder.Tests/Resources/integration.yml | 4 ---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/HttPlaceholder.Tests/Integration/Stubs/StubFileIntegrationTests.cs b/src/HttPlaceholder.Tests/Integration/Stubs/StubFileIntegrationTests.cs index 09b347dfc..0a6552cf6 100644 --- a/src/HttPlaceholder.Tests/Integration/Stubs/StubFileIntegrationTests.cs +++ b/src/HttPlaceholder.Tests/Integration/Stubs/StubFileIntegrationTests.cs @@ -1,8 +1,10 @@ -using System.Net; +using System.Linq; +using System.Net; using System.Text; namespace HttPlaceholder.Tests.Integration.Stubs; +[TestClass] public class StubFileIntegrationTests : StubIntegrationTestBase { [TestInitialize] @@ -32,6 +34,7 @@ public async Task StubIntegration_File_FileBinary_HappyFlow() var content = await response.Content.ReadAsStringAsync(); Assert.AreEqual(fileContents, content); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Assert.AreEqual("application/octet-stream", response.Content.Headers.Single(h => h.Key == "Content-Type").Value.Single()); } [TestMethod] @@ -55,5 +58,6 @@ public async Task StubIntegration_File_FileTextWithVariable_HappyFlow() var content = await response.Content.ReadAsStringAsync(); Assert.AreEqual("File contents yo! value123", content); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Assert.AreEqual("text/plain", response.Content.Headers.Single(h => h.Key == "Content-Type").Value.Single()); } } diff --git a/src/HttPlaceholder.Tests/Resources/integration.yml b/src/HttPlaceholder.Tests/Resources/integration.yml index 8911df0cd..321c6274c 100644 --- a/src/HttPlaceholder.Tests/Resources/integration.yml +++ b/src/HttPlaceholder.Tests/Resources/integration.yml @@ -900,8 +900,6 @@ equals: /text-binary.bin response: statusCode: 200 - headers: - Content-Type: text/plain enableDynamicMode: true file: text.bin @@ -913,8 +911,6 @@ equals: /text.txt response: statusCode: 200 - headers: - Content-Type: text/plain enableDynamicMode: true textFile: text.txt From a492d299f692fcc74f3f2ed5d8c6710f65472e62 Mon Sep 17 00:00:00 2001 From: Duco Date: Wed, 21 Jun 2023 20:46:53 +0200 Subject: [PATCH 07/41] Show executed stub ID when hovering over a request --- gui/src/components/request/Request.vue | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/gui/src/components/request/Request.vue b/gui/src/components/request/Request.vue index ea75b0298..27bca7cce 100644 --- a/gui/src/components/request/Request.vue +++ b/gui/src/components/request/Request.vue @@ -1,14 +1,15 @@