Skip to content
Open
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
11 changes: 10 additions & 1 deletion examples-Aspire/AspireApp1.AppHost/AspireApp1.AppHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,13 @@
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
</ItemGroup>

</Project>
<ItemGroup>
<None Update="__admin\mappings\*.proto">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="__admin\mappings\*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
27 changes: 20 additions & 7 deletions examples-Aspire/AspireApp1.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,25 @@

// IResourceBuilder<ProjectResource> apiService = builder.AddProject<Projects.AspireApp1_ApiService>("apiservice");

var mappingsPath = Path.Combine(Directory.GetCurrentDirectory(), "WireMockMappings");
var mappingsPath = Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings");

IResourceBuilder<WireMockServerResource> apiService = builder
.AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
//IResourceBuilder<WireMockServerResource> apiService1 = builder
// //.AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
// .AddWireMock("apiservice1", "http://*:8081", "grpc://*:9091")
// .AsHttp2Service()
// .WithMappingsPath(mappingsPath)
// .WithReadStaticMappings()
// .WithWatchStaticMappings()
// .WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);

IResourceBuilder<WireMockServerResource> apiService2 = builder
.AddWireMock("apiservice", args =>
{
args.WithAdditionalUrls("http://*:8081", "grpc://*:9093");
})
.AsHttp2Service()
.WithProtoDefinition("my-greeter", await File.ReadAllTextAsync(Path.Combine(mappingsPath, "greet.proto")))
.WithMappingsPath(mappingsPath)
.WithReadStaticMappings()
.WithWatchStaticMappings()
.WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);

Expand Down Expand Up @@ -45,7 +58,7 @@

builder.AddProject<Projects.AspireApp1_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(apiService)
.WaitFor(apiService);
.WithReference(apiService2)
.WaitFor(apiService2);

builder.Build().Run();
await builder.Build().RunAsync();
21 changes: 21 additions & 0 deletions examples-Aspire/AspireApp1.AppHost/__admin/mappings/greet.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
syntax = "proto3";

package greet;

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
enum PhoneType {
none = 0;
mobile = 1;
home = 2;
}
PhoneType phoneType = 2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"Guid": "351f0240-bba0-4bcb-93c6-1feba0fe0004",
"Title": "ProtoBuf Mapping 4",
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/greet.Greeter/SayHello",
"IgnoreCase": false
}
]
},
"Methods": [
"POST"
],
"Body": {
"Matcher": {
"Name": "ProtoBufMatcher",
"ProtoBufMessageType": "greet.HelloRequest"
}
}
},
"Response": {
"BodyAsJson": {
"message": "hello {{request.BodyAsJson.name}} {{request.method}}"
},
"UseTransformer": true,
"TransformerType": "Handlebars",
"TransformerReplaceNodeOptions": "EvaluateAndTryToConvert",
"Headers": {
"Content-Type": "application/grpc"
},
"TrailingHeaders": {
"grpc-status": "0"
},
"ProtoBufMessageType": "greet.HelloReply"
},
"ProtoDefinition": "my-greeter"
}
9 changes: 9 additions & 0 deletions src/WireMock.Net.Abstractions/Admin/Mappings/StatusModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,13 @@ public class StatusModel
/// The error message.
/// </summary>
public string? Error { get; set; }

/// <summary>
/// Returns a string that represents the current status model, including its unique identifier, status, and error information.
/// </summary>
/// <returns>A string containing the values of the Guid, Status, and Error properties formatted for display.</returns>
public override string ToString()
{
return $"StatusModel [Guid={Guid}, Status={Status}, Error={Error}]";
}
}
5 changes: 4 additions & 1 deletion src/WireMock.Net.Aspire/WireMock.Net.Aspire.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
</ItemGroup>

<ItemGroup>
<Compile Include="..\WireMock.Net.Minimal\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
<Compile Include="..\WireMock.Net.Minimal\Util\EnhancedFileSystemWatcher.cs" Link="Util\EnhancedFileSystemWatcher.cs" />
<Compile Include="..\WireMock.Net.Minimal\Constants\WireMockConstants.cs" Link="Constants\WireMockConstants.cs" />
<Compile Include="..\WireMock.Net.Shared\Constants\RegexConstants.cs" Link="Constants\RegexConstants.cs" />
<Compile Include="..\WireMock.Net.Minimal\Util\PortUtils.cs" Link="Util\PortUtils.cs" />
</ItemGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
Expand Down
10 changes: 6 additions & 4 deletions src/WireMock.Net.Aspire/WireMockMappingState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ namespace WireMock.Net.Aspire;

internal enum WireMockMappingState
{
NoMappings,
NotSubmitted,
Submitted,
}
NoMappings = 0,

NotSubmitted = 1,

Submitted = 2
}
52 changes: 50 additions & 2 deletions src/WireMock.Net.Aspire/WireMockServerArguments.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright © WireMock.Net

using System.Diagnostics.CodeAnalysis;
using Stef.Validation;
using WireMock.Client.Builders;
using WireMock.Util;

// ReSharper disable once CheckNamespace
namespace Aspire.Hosting;
Expand All @@ -21,10 +23,15 @@ public class WireMockServerArguments
private const string DefaultLogger = "WireMockConsoleLogger";

/// <summary>
/// The HTTP port where WireMock.Net is listening.
/// The HTTP ports where WireMock.Net is listening on.
/// If not defined, .NET Aspire automatically assigns a random port.
/// </summary>
public int? HttpPort { get; set; }
public List<int> HttpPorts { get; set; } = [];

/// <summary>
/// Additional Urls on which WireMock listens.
/// </summary>
public List<string> AdditionalUrls { get; set; } = [];

/// <summary>
/// The admin username.
Expand Down Expand Up @@ -67,6 +74,42 @@ public class WireMockServerArguments
/// </summary>
public Func<AdminApiMappingBuilder, CancellationToken, Task>? ApiMappingBuilder { get; set; }

/// <summary>
/// Grpc ProtoDefinitions.
/// </summary>
public Dictionary<string, string[]> ProtoDefinitions { get; set; } = [];

/// <summary>
/// Add an additional Urls on which WireMock should listen.
/// </summary>
/// <param name="additionalUrls">The additional urls which the WireMock Server should listen on.</param>
public void WithAdditionalUrls(params string[] additionalUrls)
{
foreach (var url in additionalUrls)
{
if (!PortUtils.TryExtract(Guard.NotNullOrEmpty(url), out _, out _, out _, out _, out var port))
{
throw new ArgumentException($"The URL '{url}' is not valid.");
}

AdditionalUrls.Add(Guard.NotNullOrWhiteSpace(url));
HttpPorts.Add(port);
}
}

/// <summary>
/// Add a Grpc ProtoDefinition at server-level.
/// </summary>
/// <param name="id">Unique identifier for the ProtoDefinition.</param>
/// <param name="protoDefinitions">The ProtoDefinition as text.</param>
public void AddProtoDefinition(string id, params string[] protoDefinitions)
{
Guard.NotNullOrWhiteSpace(id);
Guard.NotNullOrEmpty(protoDefinitions);

ProtoDefinitions[id] = protoDefinitions;
}

/// <summary>
/// Converts the current instance's properties to an array of command-line arguments for starting the WireMock.Net server.
/// </summary>
Expand Down Expand Up @@ -95,6 +138,11 @@ public string[] GetArgs()
Add(args, "--WatchStaticMappingsInSubdirectories", "true");
}

if (AdditionalUrls.Count > 0)
{
Add(args, "--Urls", $"http://*:{HttpContainerPort} {string.Join(' ', AdditionalUrls)}");
}

return args
.SelectMany(k => new[] { k.Key, k.Value })
.ToArray();
Expand Down
Loading
Loading