Skip to content

Commit 5840408

Browse files
Add Endpoint property to HttpContext and DefaultHttpContext
- Introduced an abstract Endpoint property in HttpContext for getting and setting the current request's endpoint. - Implemented the Endpoint property in DefaultHttpContext, allowing retrieval and assignment of endpoint values. - Added unit tests to verify the behavior of the Endpoint property, including default value, roundtrip setting, and consistency with extension methods.
1 parent 56ec592 commit 5840408

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

src/Http/Http.Abstractions/src/HttpContext.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ public abstract class HttpContext
7272
/// </summary>
7373
public abstract ISession Session { get; set; }
7474

75+
/// <summary>
76+
/// Gets or sets the <see cref="Endpoint"/> for the current request.
77+
/// </summary>
78+
/// <remarks>
79+
/// The endpoint for a request is typically set by routing middleware. A request might not have
80+
/// an endpoint if routing middleware hasn't run yet, or the request didn't match a route.
81+
/// </remarks>
82+
public abstract Endpoint? Endpoint { get; set; }
83+
7584
/// <summary>
7685
/// Aborts the connection underlying this request.
7786
/// </summary>
@@ -90,7 +99,7 @@ private sealed class HttpContextDebugView(HttpContext context)
9099
public HttpContextFeatureDebugView Features => new HttpContextFeatureDebugView(_context.Features);
91100
public HttpRequest Request => _context.Request;
92101
public HttpResponse Response => _context.Response;
93-
public Endpoint? Endpoint => _context.GetEndpoint();
102+
public Endpoint? Endpoint => _context.Endpoint;
94103
public ConnectionInfo Connection => _context.Connection;
95104
public WebSocketManager WebSockets => _context.WebSockets;
96105
public ClaimsPrincipal User => _context.User;

src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#nullable enable
2+
abstract Microsoft.AspNetCore.Http.HttpContext.Endpoint.get -> Microsoft.AspNetCore.Http.Endpoint?
3+
abstract Microsoft.AspNetCore.Http.HttpContext.Endpoint.set -> void
24
Microsoft.AspNetCore.Http.Metadata.IAllowCookieRedirectMetadata
35
Microsoft.AspNetCore.Http.Metadata.IDisableCookieRedirectMetadata
46
Microsoft.AspNetCore.Http.Metadata.IDisableValidationMetadata

src/Http/Http.Abstractions/test/EndpointHttpContextExtensionsTests.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,72 @@ public void SetAndGetEndpoint_Roundtrip_EndpointIsRoundtrip()
142142
Assert.Equal(initialEndpoint, endpoint);
143143
}
144144

145+
[Fact]
146+
public void EndpointProperty_Get_ReturnsNullByDefault()
147+
{
148+
// Arrange
149+
var context = new DefaultHttpContext();
150+
151+
// Act
152+
var endpoint = context.Endpoint;
153+
154+
// Assert
155+
Assert.Null(endpoint);
156+
}
157+
158+
[Fact]
159+
public void EndpointProperty_SetAndGet_Roundtrip()
160+
{
161+
// Arrange
162+
var context = new DefaultHttpContext();
163+
var testEndpoint = new Endpoint(c => Task.CompletedTask, EndpointMetadataCollection.Empty, "Test endpoint");
164+
165+
// Act
166+
context.Endpoint = testEndpoint;
167+
var retrievedEndpoint = context.Endpoint;
168+
169+
// Assert
170+
Assert.Equal(testEndpoint, retrievedEndpoint);
171+
}
172+
173+
[Fact]
174+
public void EndpointProperty_SetNull_ClearsEndpoint()
175+
{
176+
// Arrange
177+
var context = new DefaultHttpContext();
178+
var testEndpoint = new Endpoint(c => Task.CompletedTask, EndpointMetadataCollection.Empty, "Test endpoint");
179+
context.Endpoint = testEndpoint;
180+
181+
// Act
182+
context.Endpoint = null;
183+
184+
// Assert
185+
Assert.Null(context.Endpoint);
186+
}
187+
188+
[Fact]
189+
public void EndpointProperty_ConsistentWithExtensionMethods()
190+
{
191+
// Arrange
192+
var context = new DefaultHttpContext();
193+
var testEndpoint = new Endpoint(c => Task.CompletedTask, EndpointMetadataCollection.Empty, "Test endpoint");
194+
195+
// Act - Set via property
196+
context.Endpoint = testEndpoint;
197+
198+
// Assert - Both property and extension method return the same value
199+
Assert.Equal(testEndpoint, context.Endpoint);
200+
Assert.Equal(testEndpoint, context.GetEndpoint());
201+
202+
// Act - Set via extension method
203+
var newEndpoint = new Endpoint(c => Task.CompletedTask, EndpointMetadataCollection.Empty, "New endpoint");
204+
context.SetEndpoint(newEndpoint);
205+
206+
// Assert - Both property and extension method return the new value
207+
Assert.Equal(newEndpoint, context.Endpoint);
208+
Assert.Equal(newEndpoint, context.GetEndpoint());
209+
}
210+
145211
private class EndpointFeature : IEndpointFeature
146212
{
147213
public Endpoint? Endpoint { get; set; }

src/Http/Http/src/DefaultHttpContext.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,13 @@ public override ISession Session
213213
}
214214
}
215215

216+
/// <inheritdoc/>
217+
public override Endpoint? Endpoint
218+
{
219+
get { return this.GetEndpoint(); }
220+
set { this.SetEndpoint(value); }
221+
}
222+
216223
// This property exists because of backwards compatibility.
217224
// We send an anonymous object with an HttpContext property
218225
// via DiagnosticListener in various events throughout the pipeline. Instead

0 commit comments

Comments
 (0)