-
-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathBridge.cs
More file actions
112 lines (89 loc) · 3.4 KB
/
Bridge.cs
File metadata and controls
112 lines (89 loc) · 3.4 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using GenHTTP.Adapters.AspNetCore.Server;
using GenHTTP.Adapters.AspNetCore.Types;
using GenHTTP.Api.Content;
using GenHTTP.Api.Infrastructure;
using GenHTTP.Api.Protocol;
using Microsoft.AspNetCore.Http;
namespace GenHTTP.Adapters.AspNetCore.Mapping;
public static class Bridge
{
public static async ValueTask MapAsync(HttpContext context, IHandler handler, IServer? server = null, IServerCompanion? companion = null, string? registeredPath = null)
{
var actualServer = server ?? new ImplicitServer(context, handler, companion);
try
{
using var request = new Request(actualServer, context);
if (registeredPath != null)
{
AdvanceTo(request, registeredPath);
}
using var response = await handler.HandleAsync(request);
if (response == null)
{
context.Response.StatusCode = 404;
}
else
{
await WriteAsync(response, context);
actualServer.Companion?.OnRequestHandled(request, response);
}
}
catch (Exception e)
{
actualServer.Companion?.OnServerError(ServerErrorScope.ServerConnection, context.Connection.RemoteIpAddress, e);
throw;
}
}
private static async ValueTask WriteAsync(IResponse response, HttpContext context)
{
var target = context.Response;
target.StatusCode = response.Status.RawStatus;
foreach (var header in response.Headers)
{
target.Headers.Append(header.Key, header.Value);
}
if (response.Modified != null)
{
target.Headers.LastModified = response.Modified.Value.ToUniversalTime().ToString("r");
}
if (response.Expires != null)
{
target.Headers.Expires = response.Expires.Value.ToUniversalTime().ToString("r");
}
if (response.HasCookies)
{
foreach (var cookie in response.Cookies)
{
if (cookie.Value.MaxAge != null)
{
target.Cookies.Append(cookie.Key, cookie.Value.Value, new()
{
MaxAge = TimeSpan.FromSeconds(cookie.Value.MaxAge.Value)
});
}
else
{
target.Cookies.Append(cookie.Key, cookie.Value.Value);
}
}
}
if (response.Content != null)
{
target.ContentLength = (long?)response.ContentLength ?? (long?)response.Content.Length;
target.ContentType = response.ContentType?.Charset != null ? $"{response.ContentType?.RawType}; charset={response.ContentType?.Charset}" : response.ContentType?.RawType;
if (response.ContentEncoding != null)
{
target.Headers.ContentEncoding = response.ContentEncoding;
}
await response.Content.WriteAsync(target.Body, 65 * 1024);
}
}
private static void AdvanceTo(Request request, string registeredPath)
{
var parts = registeredPath.Split('/', StringSplitOptions.RemoveEmptyEntries);
foreach (var _ in parts)
{
request.Target.Advance();
}
}
}