XFEExtension
【DLL】XFE各类拓展是一个C#的DLL库,旨在优化C#代码中常用语句的使用,并提供更简洁的访问方式,同时提供Xunit测试框架,快速搭建服务器/客户端,免费ChatGPTAPI接口,免费通讯服务器,XFE下载器,新增格式等
关注
0
Fork
0
Star
0
返回提交历史
Modified
XFEExtension.NetCore/CyberComm/CyberCommHttp.cs
+4
-0
Modified
XFEExtension.NetCore/CyberComm/CyberCommRequestEventArgs.cs
+2
-0
Modified
XFEExtension.NetCore/CyberComm/CyberCommServer.cs
+22
-16
Modified
XFEExtension.NetCore/CyberComm/CyberCommServerEventArgs.cs
+9
-3
Modified
XFEExtension.NetCore/CyberComm/CyberCommServerEventArgsImpl.cs
+4
-4
Modified
XFEExtension.NetCore/XFEExtension.NetCore.csproj
+3
-1
XFEstudio/XFEExtension
公开本地监听端口属性,兼容多端口场景
CyberComm 请求上下文和 WebSocket 事件参数现已公开实际本地监听端口(LocalPort),便于在 CDN/反向代理与后端端口不一致时获取真实端口。相关方法和事件参数构造函数已调整以支持 localPort 传递和记录,CyberCommRequestEventArgs 也新增 LocalPort 属性,兼容旧 HttpListener 模式。版本号升级至 5.2.1,NuGet 包发布说明同步更新。
7a588e6
代码差异
6 个文件
+44
-24
@@ -17,6 +17,7 @@ public sealed class CyberCommHttpRequestContext
17
17
IReadOnlyDictionary<string, IReadOnlyList<string>> query,
18
18
ReadOnlyMemory<byte> body,
19
19
string clientIp,
20
int localPort,
20
21
string correlationId)
21
22
{
22
23
RequestUri = requestUri;
@@ -25,6 +26,7 @@ public sealed class CyberCommHttpRequestContext
25
26
Query = query;
26
27
Body = body;
27
28
ClientIp = clientIp;
29
LocalPort = localPort;
28
30
CorrelationId = correlationId;
29
31
}
30
32
@@ -35,6 +37,8 @@ public sealed class CyberCommHttpRequestContext
35
37
public ReadOnlyMemory<byte> Body { get; }
36
38
public string RequestBody => Encoding.UTF8.GetString(Body.Span);
37
39
public string ClientIp { get; }
40
/// <summary>实际接受当前连接的本地监听端口,不受 Host 请求头或反向代理公开端口影响。</summary>
41
public int LocalPort { get; }
38
42
public string CorrelationId { get; }
39
43
public CyberCommHttpResponse Response { get; } = new();
40
44
}
@@ -53,6 +53,8 @@ public abstract record CyberCommRequestEventArgs
53
53
public HttpListenerResponse? Response => _response;
54
54
55
55
public string ClientIP { get; }
56
/// <summary>实际接受当前连接的本地监听端口;旧 HttpListener 兼容模式下取请求 URL 端口。</summary>
57
public int LocalPort => Context?.LocalPort ?? RequestUrl?.Port ?? 0;
56
58
/// <summary>贯穿请求、响应和日志的关联标识。</summary>
57
59
public string CorrelationId => Context?.CorrelationId ?? string.Empty;
58
60
@@ -345,6 +345,7 @@ public sealed class CyberCommServer : IAsyncDisposable
345
345
{
346
346
using (client)
347
347
{
348
var localPort = ((IPEndPoint?)client.Client.LocalEndPoint)?.Port ?? endpoint.Port;
348
349
Stream stream = client.GetStream();
349
350
if (endpoint.UseTls)
350
351
{
@@ -393,14 +394,14 @@ public sealed class CyberCommServer : IAsyncDisposable
393
394
{
394
395
connection.IsWebSocket = true;
395
396
var webSocketStream = reader.DetachStream();
396
await ProcessWebSocketAsync(webSocketStream, request, options, clientIp, connection, serverToken).ConfigureAwait(false);
397
await ProcessWebSocketAsync(webSocketStream, request, options, clientIp, localPort, connection, serverToken).ConfigureAwait(false);
397
398
return;
398
399
}
399
400
400
401
connection.IsHandlingRequest = true;
401
402
try
402
403
{
403
await ProcessHttpRequestAsync(stream, request, options, clientIp, serverToken).ConfigureAwait(false);
404
await ProcessHttpRequestAsync(stream, request, options, clientIp, localPort, serverToken).ConfigureAwait(false);
404
405
}
405
406
finally
406
407
{
@@ -426,10 +427,12 @@ public sealed class CyberCommServer : IAsyncDisposable
426
427
}
427
428
}
428
429
429
private async Task ProcessHttpRequestAsync(Stream stream, CyberCommParsedRequest request, CyberCommServerOptions options, string clientIp, CancellationToken serverToken)
430
private async Task ProcessHttpRequestAsync(Stream stream, CyberCommParsedRequest request, CyberCommServerOptions options,
431
string clientIp, int localPort, CancellationToken serverToken)
430
432
{
431
433
var body = options.ReadHttpRequestBody ? request.Body : ReadOnlyMemory<byte>.Empty;
432
var context = new CyberCommHttpRequestContext(request.RequestUri, request.Method, request.Headers, request.Query, body, clientIp, Guid.NewGuid().ToString("N"));
434
var context = new CyberCommHttpRequestContext(request.RequestUri, request.Method, request.Headers, request.Query,
435
body, clientIp, localPort, Guid.NewGuid().ToString("N"));
433
436
context.Response.Headers["X-Correlation-Id"] = context.CorrelationId;
434
437
using var handlerSource = CancellationTokenSource.CreateLinkedTokenSource(serverToken);
435
438
if (options.Limits.HandlerTimeout != Timeout.InfiniteTimeSpan)
@@ -479,7 +482,7 @@ public sealed class CyberCommServer : IAsyncDisposable
479
482
}
480
483
481
484
private async Task ProcessWebSocketAsync(Stream stream, CyberCommParsedRequest request, CyberCommServerOptions options,
482
string clientIp, ActiveConnection connection, CancellationToken serverToken)
485
string clientIp, int localPort, ActiveConnection connection, CancellationToken serverToken)
483
486
{
484
487
if (!ValidateWebSocketRequest(request, out var key))
485
488
{
@@ -497,33 +500,35 @@ public sealed class CyberCommServer : IAsyncDisposable
497
500
await using var peer = new CyberCommWebSocketPeer(webSocket, options.Limits);
498
501
connection.Peer = peer;
499
502
var headers = ToNameValueCollection(request.Headers);
500
var connectedArgs = new CyberCommServerEventArgsImpl(request.RequestUri, webSocket, string.Empty, clientIp, headers, true).WithTransport(peer);
503
var connectedArgs = new CyberCommServerEventArgsImpl(request.RequestUri, webSocket, string.Empty, clientIp, headers, true, localPort).WithTransport(peer);
501
504
await InvokeWebSocketHandlerAsync(WebSocketConnectedHandler, ClientConnected, connectedArgs, serverToken).ConfigureAwait(false);
502
505
503
506
try
504
507
{
505
await ReceiveWebSocketMessagesAsync(webSocket, peer, request.RequestUri, headers, clientIp, options, serverToken).ConfigureAwait(false);
508
await ReceiveWebSocketMessagesAsync(webSocket, peer, request.RequestUri, headers, clientIp, localPort, options, serverToken).ConfigureAwait(false);
506
509
}
507
510
catch (OperationCanceledException) when (serverToken.IsCancellationRequested)
508
511
{
509
512
}
510
513
catch (Exception ex)
511
514
{
512
var errorArgs = new CyberCommServerEventArgsImpl(request.RequestUri, webSocket, new XFECyberCommException("与客户端通讯期间发生异常", ex), clientIp, headers).WithTransport(peer);
515
var errorArgs = new CyberCommServerEventArgsImpl(request.RequestUri, webSocket,
516
new XFECyberCommException("与客户端通讯期间发生异常", ex), clientIp, headers, localPort).WithTransport(peer);
513
517
await InvokeWebSocketHandlerAsync(WebSocketMessageHandler, MessageReceived, errorArgs, serverToken).ConfigureAwait(false);
514
518
}
515
519
finally
516
520
{
517
521
if (webSocket.State is WebSocketState.Open or WebSocketState.CloseReceived)
518
522
await peer.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection Closed", serverToken).ConfigureAwait(false);
519
var closedArgs = new CyberCommServerEventArgsImpl(request.RequestUri, webSocket, string.Empty, clientIp, headers, true).WithTransport(peer);
523
var closedArgs = new CyberCommServerEventArgsImpl(request.RequestUri, webSocket, string.Empty, clientIp, headers, true, localPort).WithTransport(peer);
520
524
await InvokeWebSocketHandlerAsync(WebSocketClosedHandler, ConnectionClosed, closedArgs, CancellationToken.None).ConfigureAwait(false);
521
525
connection.Peer = null;
522
526
}
523
527
}
524
528
525
529
private async Task ReceiveWebSocketMessagesAsync(WebSocket webSocket, CyberCommWebSocketPeer peer, Uri requestUri,
526
NameValueCollection headers, string clientIp, CyberCommServerOptions options, CancellationToken cancellationToken)
530
NameValueCollection headers, string clientIp, int localPort, CyberCommServerOptions options,
531
CancellationToken cancellationToken)
527
532
{
528
533
var receiveSize = Math.Clamp(BufferLength, 1024, options.Limits.MaxWebSocketFrameBytes);
529
534
var buffer = new byte[receiveSize];
@@ -541,7 +546,7 @@ public sealed class CyberCommServer : IAsyncDisposable
541
546
542
547
if (!options.AssembleWebSocketMessages)
543
548
{
544
await PublishWebSocketMessageAsync(webSocket, peer, requestUri, headers, clientIp, result.MessageType,
549
await PublishWebSocketMessageAsync(webSocket, peer, requestUri, headers, clientIp, localPort, result.MessageType,
545
550
buffer.AsMemory(0, result.Count).ToArray(), result.EndOfMessage, false, cancellationToken).ConfigureAwait(false);
546
551
continue;
547
552
}
@@ -568,13 +573,14 @@ public sealed class CyberCommServer : IAsyncDisposable
568
573
return;
569
574
}
570
575
if (result.MessageType == WebSocketMessageType.Close) break;
571
await PublishWebSocketMessageAsync(webSocket, peer, requestUri, headers, clientIp, messageType, message.ToArray(), true, true, cancellationToken).ConfigureAwait(false);
576
await PublishWebSocketMessageAsync(webSocket, peer, requestUri, headers, clientIp, localPort,
577
messageType, message.ToArray(), true, true, cancellationToken).ConfigureAwait(false);
572
578
}
573
579
}
574
580
575
581
private async Task PublishWebSocketMessageAsync(WebSocket webSocket, CyberCommWebSocketPeer peer, Uri requestUri,
576
NameValueCollection headers, string clientIp, WebSocketMessageType messageType, byte[] payload, bool endOfMessage,
577
bool validateUtf8, CancellationToken cancellationToken)
582
NameValueCollection headers, string clientIp, int localPort, WebSocketMessageType messageType, byte[] payload,
583
bool endOfMessage, bool validateUtf8, CancellationToken cancellationToken)
578
584
{
579
585
CyberCommServerEventArgs args;
580
586
if (messageType == WebSocketMessageType.Text)
@@ -586,10 +592,10 @@ public sealed class CyberCommServer : IAsyncDisposable
586
592
await peer.CloseAsync(WebSocketCloseStatus.InvalidPayloadData, "Invalid UTF-8", cancellationToken).ConfigureAwait(false);
587
593
return;
588
594
}
589
args = new CyberCommServerEventArgsImpl(requestUri, webSocket, text, clientIp, headers, endOfMessage);
595
args = new CyberCommServerEventArgsImpl(requestUri, webSocket, text, clientIp, headers, endOfMessage, localPort);
590
596
}
591
597
else if (messageType == WebSocketMessageType.Binary)
592
args = new CyberCommServerEventArgsImpl(requestUri, webSocket, payload, clientIp, headers, endOfMessage);
598
args = new CyberCommServerEventArgsImpl(requestUri, webSocket, payload, clientIp, headers, endOfMessage, localPort);
593
599
else
594
600
throw new ArgumentOutOfRangeException(nameof(messageType));
595
601
await InvokeWebSocketHandlerAsync(WebSocketMessageHandler, MessageReceived, args.WithTransport(peer), cancellationToken).ConfigureAwait(false);
@@ -22,6 +22,9 @@ public abstract record CyberCommServerEventArgs(Uri? RequestUrl, BackMessageType
22
22
private Func<ReadOnlyMemory<byte>, WebSocketMessageType, CancellationToken, ValueTask<CyberCommSendResult>>? SendHandler { get; init; }
23
23
private Func<WebSocketCloseStatus, string, CancellationToken, ValueTask<CyberCommSendResult>>? CloseHandler { get; init; }
24
24
25
/// <summary>实际接受当前连接的本地监听端口,不受 Host 请求头或反向代理公开端口影响。</summary>
26
public int LocalPort { get; internal init; }
27
25
28
/// <summary>
26
29
/// 发送文本消息
27
30
/// </summary>
@@ -102,14 +105,17 @@ public abstract record CyberCommServerEventArgs(Uri? RequestUrl, BackMessageType
102
105
throw new XFECyberCommException("强制关闭服务器端连接时出现异常", ex);
103
106
}
104
107
}
105
internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, string message, string ipAddress, NameValueCollection wsHeader, bool endOfMessage) : this(requestUrl, BackMessageType.Text, webSocket, wsHeader, null, ipAddress, message, null, endOfMessage)
108
internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, string message, string ipAddress, NameValueCollection wsHeader, bool endOfMessage, int localPort) : this(requestUrl, BackMessageType.Text, webSocket, wsHeader, null, ipAddress, message, null, endOfMessage)
106
109
{
110
LocalPort = localPort;
107
111
}
108
internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, byte[] bytes, string ipAddress, NameValueCollection wsHeader, bool endOfMessage) : this(requestUrl, BackMessageType.Binary, webSocket, wsHeader, null, ipAddress, null, bytes, endOfMessage)
112
internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, byte[] bytes, string ipAddress, NameValueCollection wsHeader, bool endOfMessage, int localPort) : this(requestUrl, BackMessageType.Binary, webSocket, wsHeader, null, ipAddress, null, bytes, endOfMessage)
109
113
{
114
LocalPort = localPort;
110
115
}
111
internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, XFECyberCommException ex, string ipAddress, NameValueCollection wsHeader) : this(requestUrl, BackMessageType.Error, webSocket, wsHeader, ex, ipAddress, null, null, true)
116
internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, XFECyberCommException ex, string ipAddress, NameValueCollection wsHeader, int localPort) : this(requestUrl, BackMessageType.Error, webSocket, wsHeader, ex, ipAddress, null, null, true)
112
117
{
118
LocalPort = localPort;
113
119
}
114
120
115
121
internal CyberCommServerEventArgs WithTransport(CyberCommWebSocketPeer peer) => this with
@@ -6,7 +6,7 @@ namespace XFEExtension.NetCore.CyberComm;
6
6
7
7
record CyberCommServerEventArgsImpl : CyberCommServerEventArgs
8
8
{
9
internal CyberCommServerEventArgsImpl(Uri? requestUrl, WebSocket webSocket, string message, string ipAddress, NameValueCollection wsHeader, bool endOfMessage) : base(requestUrl, webSocket, message, ipAddress, wsHeader, endOfMessage) { }
10
internal CyberCommServerEventArgsImpl(Uri? requestUrl, WebSocket webSocket, byte[] bytes, string ipAddress, NameValueCollection wsHeader, bool endOfMessage) : base(requestUrl, webSocket, bytes, ipAddress, wsHeader, endOfMessage) { }
11
internal CyberCommServerEventArgsImpl(Uri? requestUrl, WebSocket webSocket, XFECyberCommException ex, string ipAddress, NameValueCollection wsHeader) : base(requestUrl, webSocket, ex, ipAddress, wsHeader) { }
12
}
9
internal CyberCommServerEventArgsImpl(Uri? requestUrl, WebSocket webSocket, string message, string ipAddress, NameValueCollection wsHeader, bool endOfMessage, int localPort) : base(requestUrl, webSocket, message, ipAddress, wsHeader, endOfMessage, localPort) { }
10
internal CyberCommServerEventArgsImpl(Uri? requestUrl, WebSocket webSocket, byte[] bytes, string ipAddress, NameValueCollection wsHeader, bool endOfMessage, int localPort) : base(requestUrl, webSocket, bytes, ipAddress, wsHeader, endOfMessage, localPort) { }
11
internal CyberCommServerEventArgsImpl(Uri? requestUrl, WebSocket webSocket, XFECyberCommException ex, string ipAddress, NameValueCollection wsHeader, int localPort) : base(requestUrl, webSocket, ex, ipAddress, wsHeader, localPort) { }
12
}
@@ -5,7 +5,7 @@
5
5
<ImplicitUsings>enable</ImplicitUsings>
6
6
<Nullable>enable</Nullable>
7
7
<GenerateDocumentationFile>True</GenerateDocumentationFile>
8
<Version>5.2.0</Version>
8
<Version>5.2.1</Version>
9
9
<Title>XFEExtension</Title>
10
10
<RepositoryUrl>https://github.com/XFEstudio/XFEExtension</RepositoryUrl>
11
11
<AnalysisLevel>latest</AnalysisLevel>
@@ -20,6 +20,8 @@
20
20
<PackageReleaseNotes>
21
21
## 调整
22
22
23
CyberComm 请求上下文和 WebSocket 事件现在公开实际本地监听端口,支持 CDN/反向代理公开端口与回源端口不同的场景。
24
23
25
JSON 查询改为按访问路径惰性扫描;旧版 QueryableJsonNode 由兼容包装器提供,不再在字符串转换时构建完整节点树。
24
26
25
27
## 新增