mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 13:00:33 +01:00
Unable to add proto files from nested directories used in imports #677
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @siewers on GitHub (Mar 13, 2025).
Originally assigned to: @StefH on GitHub.
When I add proto definitions, the
WireMockProtoFileResolverwill only add the files if the filename (the first line comment in each proto file) does not contain invalid file name characters.However, when imports contain relative paths to other proto files, it fails to find them because they are not added.
I'm testing WireMock using the OpenTelemetry proto files, but they are organized in the following directory structure, which fails to work with WireMock.
I'm manually parsing each proto file and injecting the filename as the first line comment in each file; however, it doesn't work since the filename has to match the one in the imports, and I'm not allowed to use invalid filename characters, which the forward slash (
/) is.Can I make this work, or do I need to find another tool for the job?
I was thinking about creating a custom
IProtoFileResolverimplementation, but theWireMockProtoFileResolveris hard coded inProtoBufMatcher.DecodeAsync, and I don't want to reimplement the entire thing as it seems like a missing feature in WireMock.@StefH commented on GitHub (Mar 13, 2025):
I think some changes can be done to WireMockProtoFileResolver:
GetInvalidPathCharsinstead ofGetInvalidFileNameCharsThis would allow:
"// \\path\\filename.proto"or
"// /path/filename.proto"@siewers commented on GitHub (Mar 13, 2025):
That would be great.
Would it be possible to provide the proto definitions with the file path expected in the imports?
If I have an import referencing
protos/v1/something.proto, it would be great if I could create a dictionary with these files upfront, like this:Or perhaps using an type:
This could perhaps even be extended to something like this:
That way I wouldn't need to manually "hack" the files to provide it with a filename inside the file contents itself.
@StefH commented on GitHub (Mar 13, 2025):
The last one is the most user friendly I guess. The
ProtoDefinitionHelper.FromDirectory(...)method returns a dictionary which should be usable in WireMock. However, this needs a lot a changes.So maybe adding a method
ProtoDefinitionHelper.FromDirectorywhich modified the files by adding the first line comment, and then returning aIReadOnlyCollection<string> protoDefinitionswith all the modified protos --> this only needs this new method.@siewers commented on GitHub (Mar 13, 2025):
That would be an acceptable compromise I'd say 👍
The comments themselves are harmless and as long as you are not inspecting the in-memory data yourself, there should be no confusion.
@siewers commented on GitHub (Mar 13, 2025):
On a possibly unrelated note, would it be possible to get access to the deserialized proto instance through the log entries? I'm using this to assert the received messages in WireMock, but I cannot find a way to get the deserialized instances.
Let me know if I should create a separate issue for this.
@StefH commented on GitHub (Mar 13, 2025):
By deserialized, do you mean the bytes or the json?
@StefH commented on GitHub (Mar 13, 2025):
I think this PR should fix it, can you review?
https://github.com/WireMock-Net/WireMock.Net/pull/1263
Preview version is:
1.7.4-ci-19802(https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions)@siewers commented on GitHub (Mar 13, 2025):
I would like to have access to the deserialized JSON from the gRPC type.
I guess it isn't realistic to provide access to the gRPC instance as the types are generated dynamically, but perhaps available as a dynamic object could be helpful?
@StefH commented on GitHub (Mar 13, 2025):
Should already work?
@siewers commented on GitHub (Mar 13, 2025):
I mean the request message. When I make a gRPC request to WireMock, I don't see the JSON unless I set the transformer on the response.
@StefH commented on GitHub (Mar 14, 2025):
OK, in that case, it;s better to create a new issue.
@siewers commented on GitHub (Mar 14, 2025):
I must be doing something wrong. The new version works, but I'm confused about how to use it.
First thing, the imports in the proto files use a forward slash (
/) and not a back slash (\), like this:This could be solved by normalizing the path separators in the
WireMockProtoFileResolver.Existsmethod. I'm unsure if this path separator is the proto file convention, but on Windows, the implementation in theProtoDefinitionHelperdoesn't work.It also only seems to work if I add the proto definitions at the request level, but then I need to specify the "primary" proto file as the first one.
With OpenTelmetry, there are multiple primary files, so I cannot access them with this new implementation.
This is what I'm currently doing:
@StefH commented on GitHub (Mar 14, 2025):
Thanks for testing.
/), this is fixed, please test the latest preview.But as you noticed, this is not correct.
A solution could be to add an extra argument to
FromDirectory(string directory)to indicate which proto file is the main proto, and make sure to add this as first (and do not add a comment)What do you think?
@siewers commented on GitHub (Mar 14, 2025):
I don't think that would work as I load all proto files once, but later, I need to identify the main ones depending on the request.
In my example above, you can see three main proto files, one for each request type. Each of these proto files has dependencies that I need to include as well.
Ideally, I'd like not to have to worry about it at all.
If WireMock can identify the C# type based on the provided message type, why should I have to provide the files for each request?
I'd love to be able to define the list of all proto files at the server level and only specify the type at the request level. That way, there should be a correct mapping between all files and imports.
However, I don't quite understand all the different ways of mapping available, so perhaps there's something I'm missing :)
@StefH commented on GitHub (Mar 14, 2025):
1️⃣
I've changed the code, so that now you can call this once (same as you've done in your example):
And then provide the correct "List" to each mapping. Where the argument to the
ToListis the first (main) proto filename.2️⃣
This is already possible using an unique id, and maybe this fits your requirement?
See this example code:
Could this work?
@siewers commented on GitHub (Mar 15, 2025):
Yeah, I think so, but I haven't tested it yet.
However, I still find it confusing that I need to create three separate lists when all the proto files are already at the server level.
Again, I'm not sure I understand the idea behind it all (the documentation is rather scarce), but to me it seems to be a bit over complicated.
I didn't know you could or should add multiple different lists at the server level.
What I'd imagine would be a nice way of configuring it would be this:
From what I can understand, the proto files are already compiled internally to C# types, so if they are there already, wouldn't that be sufficient to look up the types?
@siewers commented on GitHub (Mar 15, 2025):
So what I think would be the least confusing setup (for me in this particular case), would be something like this:
@StefH commented on GitHub (Mar 15, 2025):
Currently, I need the id. Because currently I need the distinction between the protobuf file(sets).
For example when you want to use opentelemetry AND greet, you need to define 2 sets:
Because it could be that both have the same types.
And currently, the compiling of the texts to real types is only done when needed.
Running this at the
AddProtoDefinitionscould be possible, however then I need to loop all files and try if I can generate protobuf classes.But only providing the type ("OpenTelemetry.Proto.Collector.Trace.V1.ExportTraceServiceRequest") is also not yet supported by https://github.com/StefH/ProtoBufJsonConverter
However, maybe this is possible, because I also added logic to get info about the protobuf: get-information.
Note that you can also specify the id at mapping-level, no need to define it for the request AND the response. See this example:
https://github.com/WireMock-Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/Grpc/WireMockServerTests.Grpc.cs#L463