Skip to content
Merged
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
36 changes: 27 additions & 9 deletions src/Grpc.Net.Client/Internal/GrpcProtocolHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,7 @@ public static Metadata BuildMetadata(HttpResponseHeaders responseHeaders)

foreach (var header in responseHeaders)
{
// ASP.NET Core includes pseudo headers in the set of request headers
// whereas, they are not in gRPC implementations. We will filter them
// out when we construct the list of headers on the context.
if (header.Key.StartsWith(':'))
{
continue;
}
// Exclude grpc related headers
if (header.Key.StartsWith("grpc-", StringComparison.OrdinalIgnoreCase))
if (ShouldSkipHeader(header.Key))
{
continue;
}
Expand All @@ -91,6 +83,32 @@ public static Metadata BuildMetadata(HttpResponseHeaders responseHeaders)
return headers;
}

internal static bool ShouldSkipHeader(string name)
{
if (name.Length == 0)
{
return false;
}

switch (name[0])
{
case ':':
// ASP.NET Core includes pseudo headers in the set of request headers
// whereas, they are not in gRPC implementations. We will filter them
// out when we construct the list of headers on the context.
return true;
case 'g':
case 'G':
// Exclude known grpc headers. This matches Grpc.Core client behavior.
return string.Equals(name, GrpcProtocolConstants.StatusTrailer, StringComparison.OrdinalIgnoreCase)
|| string.Equals(name, GrpcProtocolConstants.MessageTrailer, StringComparison.OrdinalIgnoreCase)
|| string.Equals(name, GrpcProtocolConstants.MessageEncodingHeader, StringComparison.OrdinalIgnoreCase)
|| string.Equals(name, GrpcProtocolConstants.MessageAcceptEncodingHeader, StringComparison.OrdinalIgnoreCase);
default:
return false;
}
}

private const int MillisecondsPerSecond = 1000;

/* round an integer up to the next value with three significant figures */
Expand Down
15 changes: 11 additions & 4 deletions test/FunctionalTests/Client/TrailerMetadataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#endregion

using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Greet;
using Grpc.AspNetCore.FunctionalTests.Infrastructure;
Expand All @@ -35,6 +36,7 @@ public async Task GetTrailers_UnaryMethodSetStatusWithTrailers_TrailersAvailable
Task<HelloReply> UnaryDeadlineExceeded(HelloRequest request, ServerCallContext context)
{
context.ResponseTrailers.Add(new Metadata.Entry("Name", "the value was empty"));
context.ResponseTrailers.Add(new Metadata.Entry("grpc-status-details-bin", Encoding.UTF8.GetBytes("Hello world")));
context.Status = new Status(StatusCode.InvalidArgument, "Validation failed");
return Task.FromResult(new HelloReply());
}
Expand Down Expand Up @@ -65,13 +67,15 @@ Task<HelloReply> UnaryDeadlineExceeded(HelloRequest request, ServerCallContext c

// Assert
var trailers = call.GetTrailers();
Assert.AreEqual(1, trailers.Count);
Assert.AreEqual(2, trailers.Count);
Assert.AreEqual("the value was empty", trailers.GetValue("name"));
Assert.AreEqual("Hello world", Encoding.UTF8.GetString(trailers.GetValueBytes("grpc-status-details-bin")));

Assert.AreEqual(StatusCode.InvalidArgument, ex.StatusCode);
Assert.AreEqual("Validation failed", ex.Status.Detail);
Assert.AreEqual(1, ex.Trailers.Count);
Assert.AreEqual(2, ex.Trailers.Count);
Assert.AreEqual("the value was empty", ex.Trailers.GetValue("name"));
Assert.AreEqual("Hello world", Encoding.UTF8.GetString(ex.Trailers.GetValueBytes("grpc-status-details-bin")));
}

[Test]
Expand All @@ -81,6 +85,7 @@ Task<HelloReply> UnaryDeadlineExceeded(HelloRequest request, ServerCallContext c
{
var trailers = new Metadata();
trailers.Add(new Metadata.Entry("Name", "the value was empty"));
trailers.Add(new Metadata.Entry("grpc-status-details-bin", Encoding.UTF8.GetBytes("Hello world")));
return Task.FromException<HelloReply>(new RpcException(new Status(StatusCode.InvalidArgument, "Validation failed"), trailers));
}

Expand Down Expand Up @@ -110,13 +115,15 @@ Task<HelloReply> UnaryDeadlineExceeded(HelloRequest request, ServerCallContext c

// Assert
var trailers = call.GetTrailers();
Assert.GreaterOrEqual(trailers.Count, 1);
Assert.GreaterOrEqual(trailers.Count, 2);
Assert.AreEqual("the value was empty", trailers.GetValue("name"));
Assert.AreEqual("Hello world", Encoding.UTF8.GetString(trailers.GetValueBytes("grpc-status-details-bin")));

Assert.AreEqual(StatusCode.InvalidArgument, ex.StatusCode);
Assert.AreEqual("Validation failed", ex.Status.Detail);
Assert.GreaterOrEqual(ex.Trailers.Count, 1);
Assert.GreaterOrEqual(ex.Trailers.Count, 2);
Assert.AreEqual("the value was empty", ex.Trailers.GetValue("name"));
Assert.AreEqual("Hello world", Encoding.UTF8.GetString(ex.Trailers.GetValueBytes("grpc-status-details-bin")));

AssertHasLogRpcConnectionError(StatusCode.InvalidArgument, "Validation failed");
}
Expand Down
21 changes: 19 additions & 2 deletions test/Grpc.Net.Client.Tests/GrpcProtocolHelpersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@

#endregion

using System.Net.Http.Headers;
using Grpc.Net.Client.Internal;
using Grpc.Shared;
using NUnit.Framework;

namespace Grpc.Net.Client.Tests
Expand Down Expand Up @@ -54,5 +52,24 @@ public void EncodeTimeout(int milliseconds, string expected)
var encoded = GrpcProtocolHelpers.EncodeTimeout(milliseconds);
Assert.AreEqual(expected, encoded);
}

[TestCase(":status", true)]
[TestCase(":STATUS", true)]
[TestCase("grpc-status", true)]
[TestCase("GRPC-STATUS", true)]
[TestCase("grpc-message", true)]
[TestCase("GRPC-MESSAGE", true)]
[TestCase("grpc-encoding", true)]
[TestCase("GRPC-ENCODING", true)]
[TestCase("grpc-accept-encoding", true)]
[TestCase("GRPC-ACCEPT-ENCODING", true)]
[TestCase("custom", false)]
[TestCase("grpc-status-details-bin", false)]
[TestCase("GRPC-STATUS-DETAILS-BIN", false)]
public void ShouldSkipHeader(string header, bool skipped)
{
var result = GrpcProtocolHelpers.ShouldSkipHeader(header);
Assert.AreEqual(skipped, result);
}
}
}