@@ -42,11 +42,12 @@ public abstract partial class AppStartUpBase
4242 /// <summary>
4343 /// 启动 HTTP 服务器
4444 /// </summary>
45+ /// <param name="hostBuilder"></param>
4546 /// <param name="baseHandler">HTTP处理器列表,用于处理不同的HTTP请求</param>
4647 /// <param name="httpFactory">HTTP处理器工厂,根据命令标识符创建对应的处理器实例</param>
4748 /// <param name="aopHandlerTypes">AOP处理器列表,用于在HTTP请求处理前后执行额外的逻辑</param>
4849 /// <param name="minimumLevelLogLevel">日志记录的最小级别,用于控制日志输出</param>
49- private async Task StartHttpServer ( List < BaseHttpHandler > baseHandler , Func < string , BaseHttpHandler > httpFactory , List < IHttpAopHandler > aopHandlerTypes = null , LogLevel minimumLevelLogLevel = LogLevel . Debug )
50+ private async Task StartHttpServerAsync ( MultipleServerHostBuilder hostBuilder , List < BaseHttpHandler > baseHandler , Func < string , BaseHttpHandler > httpFactory , List < IHttpAopHandler > aopHandlerTypes = null , LogLevel minimumLevelLogLevel = LogLevel . Debug )
5051 {
5152 var apiRootPath = Setting . HttpUrl ;
5253 // 根路径必须以/开头和以/结尾
@@ -70,6 +71,23 @@ private async Task StartHttpServer(List<BaseHttpHandler> baseHandler, Func<strin
7071 var development = Setting . HttpIsDevelopment || builder . Environment . IsDevelopment ( ) ;
7172
7273 var openApiInfo = GetOpenApiInfo ( ) ;
74+
75+ // hostBuilder.AddServer(hostBuilder =>
76+ // {
77+ // hostBuilder.ConfigureServices((context, serviceCollection) =>
78+ // {
79+ // serviceCollection.Configure<ServerOptions>(options =>
80+ // {
81+ // var listenOptions = new ListenOptions()
82+ // {
83+ // Ip = "Any",
84+ // Port = Setting.WsPort,
85+ // };
86+ // options.AddListener(listenOptions);
87+ // });
88+ // });
89+ // });
90+
7391 if ( development )
7492 {
7593 // 添加 Swagger 服务
@@ -159,6 +177,136 @@ private async Task StartHttpServer(List<BaseHttpHandler> baseHandler, Func<strin
159177 }
160178 }
161179
180+
181+ /// <summary>
182+ /// 启动 HTTP 服务器
183+ /// </summary>
184+ /// <param name="baseHandler">HTTP处理器列表,用于处理不同的HTTP请求</param>
185+ /// <param name="httpFactory">HTTP处理器工厂,根据命令标识符创建对应的处理器实例</param>
186+ /// <param name="aopHandlerTypes">AOP处理器列表,用于在HTTP请求处理前后执行额外的逻辑</param>
187+ /// <param name="minimumLevelLogLevel">日志记录的最小级别,用于控制日志输出</param>
188+ private async Task StartHttpServer ( List < BaseHttpHandler > baseHandler , Func < string , BaseHttpHandler > httpFactory , List < IHttpAopHandler > aopHandlerTypes = null , LogLevel minimumLevelLogLevel = LogLevel . Debug )
189+ {
190+ var apiRootPath = Setting . HttpUrl ;
191+ // 根路径必须以/开头和以/结尾
192+ if ( ! Setting . HttpUrl . StartsWith ( '/' ) )
193+ {
194+ apiRootPath = "/" + Setting . HttpUrl ;
195+ }
196+
197+ if ( ! Setting . HttpUrl . EndsWith ( '/' ) )
198+ {
199+ apiRootPath += "/" ;
200+ }
201+
202+ GlobalSettings . ApiRootPath = apiRootPath ;
203+
204+ LogHelper . InfoConsole ( "启动 [HTTP] 服务器..." ) ;
205+ if ( Setting . HttpPort is > 0 and < ushort . MaxValue && NetHelper . PortIsAvailable ( Setting . HttpPort ) )
206+ {
207+ var builder = WebApplication . CreateBuilder ( ) ;
208+
209+ var development = Setting . HttpIsDevelopment || builder . Environment . IsDevelopment ( ) ;
210+
211+ var openApiInfo = GetOpenApiInfo ( ) ;
212+ if ( development )
213+ {
214+ // 添加 Swagger 服务
215+ builder . Services . AddEndpointsApiExplorer ( ) ;
216+ builder . Services . AddSwaggerGen ( options =>
217+ {
218+ options . SwaggerDoc ( openApiInfo . Version , openApiInfo ) ;
219+
220+ // 使用自定义的 SchemaFilter 来保持属性名称大小写
221+ options . SchemaFilter < PreservePropertyCasingSchemaFilter > ( ) ;
222+
223+ // 添加自定义操作过滤器来处理动态路由
224+ options . OperationFilter < SwaggerOperationFilter > ( baseHandler ) ;
225+ // 使用完整的类型名称
226+ options . CustomSchemaIds ( type => type . Name ) ;
227+ } ) ;
228+ }
229+
230+
231+ builder . WebHost . UseKestrel ( options =>
232+ {
233+ options . ListenAnyIP ( Setting . HttpPort ) ;
234+
235+ // HTTPS
236+ if ( Setting . HttpsPort > 0 && NetHelper . PortIsAvailable ( Setting . HttpsPort ) )
237+ {
238+ throw new NotImplementedException ( "HTTPS 未实现,请取消HTTPS端口配置" ) ;
239+
240+ // options.ListenAnyIP(Setting.HttpsPort, listenOptions => { listenOptions.UseHttps(); });
241+ }
242+ } ) . ConfigureLogging ( logging =>
243+ {
244+ logging . ClearProviders ( ) ;
245+ logging . AddSerilog ( Log . Logger ) ;
246+ logging . SetMinimumLevel ( minimumLevelLogLevel ) ;
247+ } )
248+ . ConfigureServices ( services =>
249+ {
250+ services . AddOpenTelemetry ( )
251+ . ConfigureResource ( configure => { configure . AddService ( "HTTP:" + Setting . ServerName + "-" + Setting . TagName , "GameFrameX.HTTP" ) . AddTelemetrySdk ( ) ; } )
252+ . WithTracing ( configure =>
253+ {
254+ configure . AddAspNetCoreInstrumentation ( ) ;
255+ configure . AddConsoleExporter ( ) ;
256+ } ) ;
257+ } ) ;
258+ var app = builder . Build ( ) ;
259+ if ( development )
260+ {
261+ // 添加 Swagger 中间件
262+ app . UseSwagger ( ) ;
263+ app . UseSwaggerUI ( options =>
264+ {
265+ options . SwaggerEndpoint ( $ "/swagger/{ openApiInfo . Version } /swagger.json", openApiInfo . Title ) ;
266+ options . RoutePrefix = "swagger" ;
267+ } ) ;
268+ var ipList = NetHelper . GetLocalIpList ( ) ;
269+ foreach ( var ip in ipList )
270+ {
271+ LogHelper . DebugConsole ( $ "Swagger UI 可通过 http://{ ip } :{ Setting . HttpPort } /swagger 访问") ;
272+ }
273+ }
274+
275+ app . UseExceptionHandler ( ExceptionHandler ) ;
276+
277+ // 每个http处理器,注册到路由中
278+ foreach ( var handler in baseHandler )
279+ {
280+ var handlerType = handler . GetType ( ) ;
281+ var mappingAttribute = handlerType . GetCustomAttribute < HttpMessageMappingAttribute > ( ) ;
282+ if ( mappingAttribute == null )
283+ {
284+ continue ;
285+ }
286+
287+ // 只支持POST请求
288+ var route = app . MapPost ( $ "{ apiRootPath } { mappingAttribute . StandardCmd } ", async ( HttpContext context , string text ) => { await HttpHandler . HandleRequest ( context , httpFactory , aopHandlerTypes ) ; } ) ;
289+ if ( development )
290+ {
291+ // 开发模式,启用 Swagger
292+ route . WithOpenApi ( operation =>
293+ {
294+ operation . Summary = "处理 POST 请求" ;
295+ operation . Description = "处理来自游戏客户端的 POST 请求" ;
296+ return operation ;
297+ } ) ;
298+ }
299+ }
300+
301+ await app . StartAsync ( ) ;
302+ LogHelper . InfoConsole ( $ "启动 [HTTP] 服务器启动完成 - 端口: { Setting . HttpPort } ") ;
303+ }
304+ else
305+ {
306+ LogHelper . Error ( $ "启动 [HTTP] 服务器 端口 [{ Setting . HttpPort } ] 被占用,无法启动HTTP服务") ;
307+ }
308+ }
309+
162310 /// <summary>
163311 /// 配置启动,当InnerIP为空时.将使用Any
164312 /// </summary>
0 commit comments