Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix new Delete with body missing from IWireMockAdminApi interface #413

Merged
Merged
8 changes: 8 additions & 0 deletions src/WireMock.Net.RestClient/IWireMockAdminApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ public interface IWireMockAdminApi
[Delete("mappings")]
Task<StatusModel> DeleteMappingsAsync();

/// <summary>
/// Delete mappings according to GUIDs
/// </summary>
/// <param name="mappings">MappingModels</param>
[Delete("mappings")]
[Header("Content-Type", "application/json")]
Task<StatusModel> DeleteMappingsAsync([Body] IList<MappingModel> mappings);

/// <summary>
/// Delete (reset) all mappings.
/// </summary>
Expand Down
60 changes: 56 additions & 4 deletions src/WireMock.Net/Server/WireMockServer.Admin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -555,11 +555,63 @@ private ResponseMessage MappingsPost(RequestMessage requestMessage)

private ResponseMessage MappingsDelete(RequestMessage requestMessage)
{
ResetMappings();
if (!string.IsNullOrEmpty(requestMessage.Body))
{
var deletedGuids = MappingsDeleteMappingFromBody(requestMessage);
if (deletedGuids != null)
{
return ResponseMessageBuilder.Create($"Mappings deleted. Affected GUIDs: [{string.Join(", ", deletedGuids.ToArray())}]");
}
else
{
// return bad request
return ResponseMessageBuilder.Create("Poorly formed mapping JSON.", 400);
}
}
else
{
ResetMappings();

ResetScenarios();
ResetScenarios();

return ResponseMessageBuilder.Create("Mappings deleted");
}
}

private IEnumerable<Guid> MappingsDeleteMappingFromBody(RequestMessage requestMessage)
{
var deletedGuids = new List<Guid>();

try
{
var mappingModels = DeserializeRequestMessageToArray<MappingModel>(requestMessage);
foreach (var mappingModel in mappingModels)
{
if (mappingModel.Guid.HasValue)
{
if (DeleteMapping(mappingModel.Guid.Value))
{
deletedGuids.Add(mappingModel.Guid.Value);
}
else
{
_settings.Logger.Debug($"Did not find/delete mapping with GUID: {mappingModel.Guid.Value}.");
}
}
}
}
catch (ArgumentException a)
{
_settings.Logger.Error("ArgumentException: {0}", a);
return null;
}
catch (Exception e)
{
_settings.Logger.Error("Exception: {0}", e);
return null;
}

return ResponseMessageBuilder.Create("Mappings deleted");
return deletedGuids;
}

private ResponseMessage MappingsReset(RequestMessage requestMessage)
Expand Down Expand Up @@ -873,7 +925,7 @@ private ResponseMessage ToJson<T>(T result, bool keepNullValues = false)
DetectedBodyType = BodyType.String,
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _jsonSerializerSettings)
},
StatusCode = (int) HttpStatusCode.OK,
StatusCode = (int)HttpStatusCode.OK,
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(ContentTypeJson) } }
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/WireMock.Net/Util/BodyParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal static class BodyParser
{ "GET", false },
{ "PUT", true },
{ "POST", true },
{ "DELETE", false },
{ "DELETE", true },
{ "TRACE", false },
{ "OPTIONS", true },
{ "CONNECT", false },
Expand Down
2 changes: 1 addition & 1 deletion test/WireMock.Net.Tests/Util/BodyParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string
[InlineData("GET", false)]
[InlineData("PUT", true)]
[InlineData("POST", true)]
[InlineData("DELETE", false)]
[InlineData("DELETE", true)]
[InlineData("TRACE", false)]
[InlineData("OPTIONS", true)]
[InlineData("CONNECT", false)]
Expand Down
63 changes: 62 additions & 1 deletion test/WireMock.Net.Tests/WireMockServer.Admin.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Moq;
using Newtonsoft.Json;
Expand Down Expand Up @@ -42,7 +45,6 @@ public void WireMockServer_Admin_StartStop()
public void WireMockServer_Admin_ResetMappings()
{
var server = WireMockServer.Start();

string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings");
server.ReadStaticMappings(folder);

Expand Down Expand Up @@ -404,5 +406,64 @@ public void WireMockServer_Admin_AddMappingsAndSaveToFile()
staticMappingHandlerMock.Verify(m => m.FolderExists("folder"), Times.Once);
staticMappingHandlerMock.Verify(m => m.WriteMappingFile(Path.Combine("folder", guid + ".json"), It.IsAny<string>()), Times.Once);
}

[Fact]
public async void WireMockServer_Admin_DeleteMappings()
{
// Arrange
var server = WireMockServer.Start(new WireMockServerSettings
{
StartAdminInterface = true,
ReadStaticMappings = false,
WatchStaticMappings = false,
WatchStaticMappingsInSubdirectories = false
});

server
.Given(Request.Create().WithPath("/path1"))
.AtPriority(0)
.RespondWith(Response.Create().WithStatusCode(200));
server
.Given(Request.Create().WithPath("/path2"))
.AtPriority(1)
.RespondWith(Response.Create().WithStatusCode(200));
server
.Given(Request.Create().WithPath("/path3"))
.AtPriority(2)
.RespondWith(Response.Create().WithStatusCode(200));

Check.That(server.MappingModels.Count()).Equals(3);

Guid? guid1 = server.MappingModels.ElementAt(0).Guid;
Guid? guid2 = server.MappingModels.ElementAt(1).Guid;
Guid? guid3 = server.MappingModels.ElementAt(2).Guid;

Check.That(guid1).IsNotNull();
Check.That(guid2).IsNotNull();
Check.That(guid3).IsNotNull();

string guidsJsonBody = $"[" +
$"{{\"Guid\": \"{guid1}\"}}," +
$"{{\"Guid\": \"{guid2}\"}}" +
$"]";

// Act
var request = new HttpRequestMessage()
{
Method = HttpMethod.Delete,
RequestUri = new Uri($"http://localhost:{server.Ports[0]}/__admin/mappings"),
Content = new StringContent(guidsJsonBody, Encoding.UTF8, "application/json")
};

var response = await new HttpClient().SendAsync(request);

// Assert
IEnumerable<Guid> guids = server.MappingModels.Select(mapping => mapping.Guid.Value);
Check.That(guids.Contains(guid1.Value)).IsFalse();
Check.That(guids.Contains(guid2.Value)).IsFalse();
Check.That(guids.Contains(guid3.Value)).IsTrue();
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
Check.That(await response.Content.ReadAsStringAsync()).Equals($"{{\"Status\":\"Mappings deleted. Affected GUIDs: [{guid1}, {guid2}]\"}}");
}
}
}
6 changes: 3 additions & 3 deletions test/WireMock.Net.Tests/WireMockServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,10 @@ public async Task WireMockServer_Should_exclude_restrictedResponseHeader()
Check.That(response.Headers.Contains("Transfer-Encoding")).IsFalse();
}

[Theory]
[InlineData("DELETE")]
#if !NET452
[Theory]
[InlineData("TRACE")]
[InlineData("GET")]
#endif
public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_definitely_disallowed(string method)
{
// Assign
Expand All @@ -189,12 +187,14 @@ public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_d
// Assert
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
}
#endif

[Theory]
[InlineData("POST")]
[InlineData("PUT")]
[InlineData("OPTIONS")]
[InlineData("REPORT")]
[InlineData("DELETE")]
[InlineData("SOME-UNKNOWN-METHOD")] // default behavior for unknown methods is to allow a body (see BodyParser.ShouldParseBody)
public async Task WireMockServer_Should_not_exclude_body_for_supported_methods(string method)
{
Expand Down