Skip to content

Commit d953d75

Browse files
Enable endpoint for requests mapped via ASP.NET Core adapter (#712)
1 parent 838b9f5 commit d953d75

8 files changed

Lines changed: 74 additions & 42 deletions

File tree

Adapters/AspNetCore/Mapping/Bridge.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using GenHTTP.Adapters.AspNetCore.Server;
22
using GenHTTP.Adapters.AspNetCore.Types;
3+
34
using GenHTTP.Api.Content;
45
using GenHTTP.Api.Infrastructure;
56
using GenHTTP.Api.Protocol;
7+
68
using Microsoft.AspNetCore.Http;
79

810
namespace GenHTTP.Adapters.AspNetCore.Mapping;
@@ -12,7 +14,7 @@ public static class Bridge
1214

1315
public static async ValueTask MapAsync(HttpContext context, IHandler handler, IServer? server = null, IServerCompanion? companion = null, string? registeredPath = null)
1416
{
15-
var actualServer = server ?? new ImplicitServer(handler, companion);
17+
var actualServer = server ?? new ImplicitServer(context, handler, companion);
1618

1719
try
1820
{

Adapters/AspNetCore/Server/EmptyEndpoints.cs

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using GenHTTP.Api.Infrastructure;
2+
using Microsoft.AspNetCore.Http;
3+
4+
namespace GenHTTP.Adapters.AspNetCore.Server;
5+
6+
public class EndpointCollection : List<IEndPoint>, IEndPointCollection
7+
{
8+
9+
public EndpointCollection(HttpContext context)
10+
{
11+
Add(new ImplicitEndpoint(context));
12+
}
13+
14+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Net;
2+
3+
using GenHTTP.Api.Infrastructure;
4+
5+
using Microsoft.AspNetCore.Http;
6+
7+
namespace GenHTTP.Adapters.AspNetCore.Server;
8+
9+
public class ImplicitEndpoint(HttpContext context) : IEndPoint
10+
{
11+
12+
public IPAddress? Address => context.Connection.LocalIpAddress;
13+
14+
public ushort Port => (ushort)context.Connection.LocalPort;
15+
16+
public bool Secure => context.Request.IsHttps;
17+
18+
public void Dispose()
19+
{
20+
// nop
21+
}
22+
23+
}

Adapters/AspNetCore/Server/ImplicitServer.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using GenHTTP.Api.Content;
44
using GenHTTP.Api.Infrastructure;
55

6+
using Microsoft.AspNetCore.Http;
7+
68
namespace GenHTTP.Adapters.AspNetCore.Server;
79

810
public sealed class ImplicitServer : IServer
@@ -33,12 +35,12 @@ public bool Development
3335

3436
#region Initialization
3537

36-
public ImplicitServer(IHandler handler, IServerCompanion? companion)
38+
public ImplicitServer(HttpContext context, IHandler handler, IServerCompanion? companion)
3739
{
3840
Handler = handler;
3941
Companion = companion;
4042

41-
EndPoints = new EmptyEndpoints();
43+
EndPoints = new EndpointCollection(context);
4244

4345
Running = true;
4446
}

Adapters/AspNetCore/Types/Request.cs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,27 @@ namespace GenHTTP.Adapters.AspNetCore.Types;
1212

1313
public sealed class Request : IRequest
1414
{
15-
private RequestProperties? _Properties;
15+
private RequestProperties? _properties;
1616

17-
private Query? _Query;
17+
private Query? _query;
1818

19-
private Cookies? _Cookies;
19+
private Cookies? _cookies;
2020

21-
private readonly ForwardingCollection _Forwardings = new();
21+
private readonly ForwardingCollection _forwardings = new();
2222

23-
private Headers? _Headers;
24-
25-
private readonly IEndPoint? _EndPoint;
23+
private Headers? _headers;
2624

2725
#region Get-/Setters
2826

2927
public IRequestProperties Properties
3028
{
31-
get { return _Properties ??= new RequestProperties(); }
29+
get { return _properties ??= new RequestProperties(); }
3230
}
3331

3432
public IServer Server { get; }
3533

36-
public IEndPoint EndPoint => _EndPoint ?? throw new InvalidOperationException("EndPoint is not available as it is managed by ASP.NET Core");
37-
34+
public IEndPoint EndPoint { get; }
35+
3836
public IClientConnection Client { get; }
3937

4038
public IClientConnection LocalClient { get; }
@@ -55,19 +53,19 @@ public IRequestProperties Properties
5553

5654
public IRequestQuery Query
5755
{
58-
get { return _Query ??= new Query(Context); }
56+
get { return _query ??= new Query(Context); }
5957
}
6058

6159
public ICookieCollection Cookies
6260
{
63-
get { return _Cookies ??= new Cookies(Context); }
61+
get { return _cookies ??= new Cookies(Context); }
6462
}
6563

66-
public IForwardingCollection Forwardings => _Forwardings;
64+
public IForwardingCollection Forwardings => _forwardings;
6765

6866
public IHeaderCollection Headers
6967
{
70-
get { return _Headers ??= new Headers(Context); }
68+
get { return _headers ??= new Headers(Context); }
7169
}
7270

7371
public Stream Content => Context.BodyReader.AsStream(true);
@@ -101,19 +99,19 @@ public Request(IServer server, HttpContext context)
10199
{
102100
foreach (var entry in forwardings)
103101
{
104-
if (entry != null) _Forwardings.Add(entry);
102+
if (entry != null) _forwardings.Add(entry);
105103
}
106104
}
107105
else
108106
{
109-
_Forwardings.TryAddLegacy(Headers);
107+
_forwardings.TryAddLegacy(Headers);
110108
}
111109

112110
LocalClient = new ClientConnection(context.Connection, context.Request);
113111

114-
Client = _Forwardings.DetermineClient(context.Connection.ClientCertificate) ?? LocalClient;
112+
Client = _forwardings.DetermineClient(context.Connection.ClientCertificate) ?? LocalClient;
115113

116-
_EndPoint = Server.EndPoints.FirstOrDefault(e => e.Port == context.Connection.LocalPort);
114+
EndPoint = Server.EndPoints.First(e => e.Port == context.Connection.LocalPort);
117115
}
118116

119117
#endregion
@@ -128,15 +126,15 @@ public Request(IServer server, HttpContext context)
128126

129127
#region Lifecycle
130128

131-
private bool _Disposed;
129+
private bool _disposed;
132130

133131
public void Dispose()
134132
{
135-
if (!_Disposed)
133+
if (!_disposed)
136134
{
137-
_Properties?.Dispose();
135+
_properties?.Dispose();
138136

139-
_Disposed = true;
137+
_disposed = true;
140138
}
141139
}
142140

Testing/Acceptance/Adapters/AspNetCore/IntegrationTests.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,14 @@ public async Task TestImplicitServer()
9696
{
9797
app.Map("/server", Inline.Create().Get(async (IRequest r) =>
9898
{
99-
await r.Server.DisposeAsync(); // nop
100-
101-
await Assert.ThrowsExactlyAsync<InvalidOperationException>(async () => await r.Server.StartAsync());
102-
103-
return r.Server;
99+
var server = r.Server;
100+
101+
await server.DisposeAsync(); // nop
102+
103+
await Assert.ThrowsExactlyAsync<InvalidOperationException>(async () => await server.StartAsync());
104+
105+
Assert.IsTrue(server.Running);
106+
Assert.IsFalse(server.Development);
104107
}));
105108
};
106109

@@ -110,13 +113,7 @@ public async Task TestImplicitServer()
110113

111114
using var response = await GetResponseAsync(client, "/server", port);
112115

113-
await response.AssertStatusAsync(HttpStatusCode.OK);
114-
115-
var content = await response.GetContentAsync();
116-
117-
AssertX.Contains("\"running\":true", content);
118-
AssertX.Contains("\"development\":false", content);
119-
AssertX.Contains("\"version\"", content);
116+
await response.AssertStatusAsync(HttpStatusCode.NoContent);
120117
}
121118

122119
#endregion

Testing/Acceptance/Modules/Basics/RedirectTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,5 @@ public async Task TestAbsoluteRoute(TestEngine engine)
8383

8484
Assert.AreEqual("/me/to/", new Uri(response.GetHeader("Location")!).AbsolutePath);
8585
}
86+
8687
}

0 commit comments

Comments
 (0)