This repository was archived by the owner on Dec 2, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathGrpcWebMiddleware.cs
More file actions
78 lines (68 loc) · 2.84 KB
/
Copy pathGrpcWebMiddleware.cs
File metadata and controls
78 lines (68 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Logging;
namespace Knowit.Grpc.Web
{
internal class GrpcWebMiddleware : IHttpResponseTrailersFeature
{
private static readonly Regex ContentType = new Regex(
@"application/grpc-web(?:-(?<text>text))?(?:\+(?<format>\w+))?");
private readonly RequestDelegate _next;
private readonly ILogger<GrpcWebMiddleware> _logger;
private readonly BinaryTranscoder _binaryTranscoder;
private readonly Base64Transcoder _base64Transcoder;
public IHeaderDictionary Trailers { get; set; } = new HeaderDictionary();
public GrpcWebMiddleware(
RequestDelegate next,
ILogger<GrpcWebMiddleware> logger,
BinaryTranscoder binaryTranscoder,
Base64Transcoder base64Transcoder)
{
_next = next;
_logger = logger;
_binaryTranscoder = binaryTranscoder;
_base64Transcoder = base64Transcoder;
}
public async Task Invoke(HttpContext context)
{
var match = ContentType.Match(context.Request.ContentType ?? "");
if (match.Success)
{
_logger.LogInformation("Intercepted gRPC Web request to {Uri}", context.Request.Path.Value);
var isText = match.Groups["text"].Success;
var format = match.Groups["format"].Success ? match.Groups["format"].Value : null;
var transcoder = isText ? (ITranscoder) _base64Transcoder : _binaryTranscoder;
await Intercept(context, isText, format, transcoder);
}
else
{
await _next(context);
}
}
private async Task Intercept(HttpContext context, bool isText, string format, ITranscoder transcoder)
{
var textPostfix = isText ? "-text" : "";
var formatPostfix = format != null ? $"+{format}" : "";
context.Features.Set<IHttpResponseTrailersFeature>(this);
context.Request.Protocol = "HTTP/2";
context.Request.ContentType = $"application/grpc{formatPostfix}";
context.Response.OnStarting(() =>
{
context.Response.ContentType = $"application/grpc-web{textPostfix}{formatPostfix}";
return Task.CompletedTask;
});
await transcoder.TranscodeStream(_next);
if (Trailers.Count > 0)
{
_logger.LogDebug("Adding trailers");
await transcoder.TranscodeTrailers(Trailers);
}
else
{
_logger.LogDebug("Skipping trailers");
}
}
}
}