diff --git a/src/WireMock.Net.Abstractions/Models/IdOrTexts.cs b/src/WireMock.Net.Abstractions/Models/IdOrTexts.cs
index 7a7a03e0..6ee3c085 100644
--- a/src/WireMock.Net.Abstractions/Models/IdOrTexts.cs
+++ b/src/WireMock.Net.Abstractions/Models/IdOrTexts.cs
@@ -16,7 +16,7 @@ public readonly struct IdOrTexts
public string? Id { get; }
///
- /// The Text.
+ /// The Texts.
///
public IReadOnlyList Texts { get; }
@@ -41,7 +41,7 @@ public IdOrTexts(string? id, IReadOnlyList texts)
}
///
- /// When Id is defined, return process the Id, else process the Texts.
+ /// When Id is defined, process the Id, else process the Texts.
///
/// Callback to process the id.
/// Callback to process the texts.
diff --git a/src/WireMock.Net/Util/WireMockProtoFileResolver.cs b/src/WireMock.Net/Util/WireMockProtoFileResolver.cs
index 86250a1d..cbae432c 100644
--- a/src/WireMock.Net/Util/WireMockProtoFileResolver.cs
+++ b/src/WireMock.Net/Util/WireMockProtoFileResolver.cs
@@ -2,6 +2,7 @@
#if PROTOBUF
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using ProtoBufJsonConverter;
@@ -9,21 +10,29 @@
namespace WireMock.Util;
+///
+/// This resolver is used to resolve the extra ProtoDefinition files.
+/// It assumes that:
+/// - the first ProtoDefinition file is the main ProtoDefinition file.
+/// - the first commented line of each extra ProtoDefinition file is the filename which is used in the import of the other ProtoDefinition file(s).
+///
internal class WireMockProtoFileResolver : IProtoFileResolver
{
private readonly Dictionary _files = new();
public WireMockProtoFileResolver(IReadOnlyCollection protoDefinitions)
{
- if (Guard.NotNullOrEmpty(protoDefinitions).Count() > 1)
+ if (Guard.NotNullOrEmpty(protoDefinitions).Count() <= 1)
{
- foreach (var extraProtoDefinition in protoDefinitions.Skip(1))
+ return;
+ }
+
+ foreach (var extraProtoDefinition in protoDefinitions.Skip(1))
+ {
+ var firstNonEmptyLine = extraProtoDefinition.Split(['\r', '\n']).FirstOrDefault(l => !string.IsNullOrEmpty(l));
+ if (firstNonEmptyLine != null && TryGetValidFileName(firstNonEmptyLine.TrimStart(['/', ' ']), out var validFileName))
{
- var firstNonEmptyLine = extraProtoDefinition.Split(['\r', '\n']).FirstOrDefault(l => !string.IsNullOrEmpty(l));
- if (firstNonEmptyLine != null)
- {
- _files.Add(firstNonEmptyLine.TrimStart(['\r', '\n', '/', ' ']), extraProtoDefinition);
- }
+ _files.Add(validFileName, extraProtoDefinition);
}
}
}
@@ -42,5 +51,17 @@ public TextReader OpenText(string path)
throw new FileNotFoundException($"The ProtoDefinition '{path}' was not found.");
}
+
+ private static bool TryGetValidFileName(string fileName, [NotNullWhen(true)] out string? validFileName)
+ {
+ if (!fileName.Any(c => Path.GetInvalidFileNameChars().Contains(c)))
+ {
+ validFileName = fileName;
+ return true;
+ }
+
+ validFileName = null;
+ return false;
+ }
}
#endif
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Grpc/ProtoBufUtilsTests.cs b/test/WireMock.Net.Tests/Grpc/ProtoBufUtilsTests.cs
new file mode 100644
index 00000000..c8ff777c
--- /dev/null
+++ b/test/WireMock.Net.Tests/Grpc/ProtoBufUtilsTests.cs
@@ -0,0 +1,41 @@
+// Copyright © WireMock.Net
+
+#if PROTOBUF
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using FluentAssertions;
+using WireMock.Util;
+using Xunit;
+
+namespace WireMock.Net.Tests.Grpc;
+
+public class ProtoBufUtilsTests
+{
+ [Fact]
+ public async Task GetProtoBufMessageWithHeader_MultipleProtoFiles()
+ {
+ // Arrange
+ var greet = await ReadProtoFileAsync("greet1.proto");
+ var request = await ReadProtoFileAsync("request.proto");
+
+ // Act
+ var responseBytes = await ProtoBufUtils.GetProtoBufMessageWithHeaderAsync(
+ [greet, request],
+ "greet.HelloRequest",
+ new
+ {
+ name = "hello"
+ }
+ );
+
+ // Assert
+ Convert.ToBase64String(responseBytes).Should().Be("AAAAAAcKBWhlbGxv");
+ }
+
+ private static Task ReadProtoFileAsync(string filename)
+ {
+ return File.ReadAllTextAsync(Path.Combine(Directory.GetCurrentDirectory(), "Grpc", filename));
+ }
+}
+#endif
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Grpc/greet1.proto b/test/WireMock.Net.Tests/Grpc/greet1.proto
new file mode 100644
index 00000000..5a263360
--- /dev/null
+++ b/test/WireMock.Net.Tests/Grpc/greet1.proto
@@ -0,0 +1,13 @@
+syntax = "proto3";
+
+import "request.proto";
+
+package greet;
+
+service Greeter {
+ rpc SayHello (HelloRequest) returns (HelloReply);
+}
+
+message HelloReply {
+ string message = 1;
+}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Grpc/request.proto b/test/WireMock.Net.Tests/Grpc/request.proto
new file mode 100644
index 00000000..8e9f4683
--- /dev/null
+++ b/test/WireMock.Net.Tests/Grpc/request.proto
@@ -0,0 +1,8 @@
+// request.proto
+syntax = "proto3";
+
+package greet;
+
+message HelloRequest {
+ string name = 1;
+}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj
index 038dafaf..adf1c50c 100644
--- a/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj
+++ b/test/WireMock.Net.Tests/WireMock.Net.Tests.csproj
@@ -134,6 +134,14 @@
PreserveNewest
+
+ PreserveNewest
+
+
+
+ PreserveNewest
+
+
PreserveNewest
Client