.NET 4.8类库项目如何记录对外发出的HTTP请求?
排查.NET 4.8 DLL中意外GET请求的方法及HTTP请求全量记录方案
问题背景
我有一个对接ERP系统的.NET 4.8 DLL类库,会向Unix环境的第三方Web应用发起REST请求。目前排查异常时发现,第三方反馈收到大量来自该DLL、针对仅支持PATCH/POST的URL的GET请求,其中某一URL甚至根本没配置GET功能。
我梳理代码后发现,只有一处入口发送PATCH请求(代码示例如下),但不确定是否存在.NET底层对象自动发起HTTP调用的可能。现在需要记录DLL发出的所有HTTP请求,以确认这些异常GET请求的来源。我查了一些日志方案,但大多针对Web项目,不确定是否适用于DLL。
现有代码示例
try { CVToken curToken = CVGlobalRestCalls.GetToken(Session); HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", curToken.Token); httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); var jSettings = new JsonSerializerSettings(); HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), string.Format("{0}/readytosend/{1}/complete", Globals.GetRESTURL(Session), JobID)); request.Content = new StringContent(JsonConvert.SerializeObject(string.Empty, Formatting.Indented, jSettings), Encoding.Default, "application/json-patch+json"); HttpResponseMessage response = httpClient.SendAsync(request).Result; CVJob cvCompletedJob = JsonConvert.DeserializeObject<CVJob>(CVGlobalRestCalls.GetResponseContent(response)); outFile.WriteLine(string.Format("Invoice Group {0} has been pushed to CV", JobID.ToString())); } catch (Exception ex) { throw new Exception(string.Format(" {0}", ex.Message)); }
解决方案
一、先排查自动发起请求的潜在原因
- 重定向导致方法变更:
HttpClient默认会自动跟随3xx重定向,部分场景下POST/PATCH请求会被转为GET。可以在创建HttpClient前禁用自动重定向验证:var handler = new HttpClientHandler { AllowAutoRedirect = false }; HttpClient httpClient = new HttpClient(handler); - 隐藏的内部请求:检查
CVGlobalRestCalls.GetToken和CVGlobalRestCalls.GetResponseContent方法内部,是否有发起额外GET请求的逻辑——这两个方法很可能是异常请求的来源。
二、给DLL添加全量HTTP请求日志的三种方案
1. 自定义HttpClient拦截器(最灵活)
直接通过DelegatingHandler拦截所有请求,完全可控,适用于DLL:
public class LoggingHandler : DelegatingHandler { private readonly TextWriter _logWriter; public LoggingHandler(TextWriter logWriter) { _logWriter = logWriter; InnerHandler = new HttpClientHandler(); } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // 记录请求核心信息 await _logWriter.WriteLineAsync($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 请求方法: {request.Method}, 请求URL: {request.RequestUri}"); // 可选:记录请求体和头部 if (request.Content != null) { var content = await request.Content.ReadAsStringAsync(); await _logWriter.WriteLineAsync($"请求体内容: {content}"); } foreach (var header in request.Headers) { await _logWriter.WriteLineAsync($"请求头 {header.Key}: {string.Join(", ", header.Value)}"); } // 发送请求并记录响应 var response = await base.SendAsync(request, cancellationToken); await _logWriter.WriteLineAsync($"响应状态码: {response.StatusCode}"); return response; } }
然后修改你的HttpClient初始化代码:
// 替换原有的new HttpClient() var logFile = new StreamWriter("dll_http_logs.log", true); HttpClient httpClient = new HttpClient(new LoggingHandler(logFile));
所有通过这个HttpClient的请求都会被写入日志文件。
2. 系统诊断跟踪日志(无需改代码)
直接通过配置文件开启.NET自带的跟踪日志,捕获所有HTTP相关流量:
在DLL所在应用的app.config中添加如下配置:
<configuration> <system.diagnostics> <sources> <source name="System.Net.Http" switchValue="Verbose"> <listeners> <add name="httpTraceListener" /> </listeners> </source> <!-- 可选:添加System.Net捕获更底层的网络日志 --> <source name="System.Net" switchValue="Verbose"> <listeners> <add name="httpTraceListener" /> </listeners> </source> </sources> <sharedListeners> <add name="httpTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="net_http_trace.log" /> </sharedListeners> <trace autoflush="true" indentsize="4" /> </system.diagnostics> </configuration>
运行后会生成net_http_trace.log,里面包含所有HTTP请求的详细信息。
3. 本地抓包工具辅助验证
如果上述方法还找不到问题,可以用Fiddler或Wireshark在本地抓包,直接查看所有从当前机器发出的HTTP请求,包括请求来源进程、方法、URL等,快速定位异常请求的发起方。
内容的提问来源于stack exchange,提问作者sdMike77
相关产品推荐
相关产品推荐

