C#如何创建集成API且可监听记录所有API调用的HTTP服务器
问题根因
你现有代码无法运行的核心原因是两个独立HTTP监听器同时尝试绑定8080端口:自定义的HttpServer(底层基于HttpListener实现)和后续启动的HttpSelfHostServer属于完全独立的监听实例,操作系统默认不允许多个实例无特殊配置时独占监听同一端口,启动时必然抛出端口占用异常。
完全不需要拆分两个独立服务,也不用单独启动HttpListener做请求监听,直接复用ASP.NET Web API SelfHost的原生请求管道做日志埋点即可,天然规避端口冲突,还能拿到完整的请求、响应数据。
正确实现方案
第一步:实现全局日志拦截处理器
自定义消息处理器继承DelegatingHandler,所有经过HTTP服务的请求、响应都会先经过这个处理器,在这里完成全量日志记录即可,不需要额外启动监听服务:
public class RequestLoggingHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { // 记录请求基础信息:路径、方法、请求头、请求时间、客户端IP var requestInfo = new { Path = request.RequestUri.AbsolutePath, Method = request.Method.Method, Headers = request.Headers.ToDictionary(h => h.Key, h => string.Join(";", h.Value)), RequestTime = DateTime.Now, ClientIP = request.GetOwinContext().Request.RemoteIpAddress }; // 此处可按需将请求日志写入文件、数据库或做其他处理 Log.Info($"收到请求: {JsonConvert.SerializeObject(requestInfo)}"); // 将请求传递到后续管道,执行实际API业务逻辑 var response = await base.SendAsync(request, cancellationToken); // 记录响应信息:状态码、处理耗时、响应内容 var responseInfo = new { StatusCode = (int)response.StatusCode, CostMs = (DateTime.Now - requestInfo.RequestTime).TotalMilliseconds, Content = await response.Content.ReadAsStringAsync(cancellationToken) }; Log.Info($"请求处理完成: {JsonConvert.SerializeObject(responseInfo)}"); return response; } }
第二步:调整服务启动代码
删掉原有单独启动自定义HttpServer的逻辑,仅保留一个HttpSelfHostServer实例,将日志处理器注册到服务管道中:
static void Main(string[] args) { Console.WriteLine("Starting HTTP server..."); var config = new HttpSelfHostConfiguration("http://localhost:8080/"); // 注册API路由 config.Routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); // 注册全局日志拦截器 config.MessageHandlers.Add(new RequestLoggingHandler()); using (HttpSelfHostServer server = new HttpSelfHostServer(config)) { server.OpenAsync().Wait(); Console.WriteLine("Server started at http://localhost:8080/, Press Enter to quit."); Console.ReadLine(); server.CloseAsync().Wait(); } Console.WriteLine("Exiting gracefully..."); }
方案适配性说明
该方案完全匹配你设计的Hub-Node分布式架构需求:
- 正常对外提供API服务能力:所有
/api/前缀的请求会正常路由到对应Controller处理,节点注册、心跳、任务日志上报等业务接口可正常开发使用 - 全量通信日志无遗漏:所有发往Hub的请求,不管是Windows Node节点的调用还是其他外部API请求,都会被日志处理器拦截,可按需记录任意维度的通信数据
- 彻底规避端口冲突:整个服务仅存在一个HTTP监听实例绑定指定端口,不存在多实例抢占端口的问题
注意事项:如果使用较老版本的Web API SelfHost,获取客户端IP需要先安装
Microsoft.AspNet.WebApi.OwinSelfHost包,通过OWIN上下文读取;如果需要记录请求体内容,读取请求流后记得将流的Position重置为0,否则后续业务逻辑无法读取请求报文会报错。
内容的提问来源于stack exchange,提问作者Michał Cichoń
相关产品推荐
相关产品推荐

