如何在不发出请求的情况下捕获HttpClient请求

时间:2020-10-06 16:38:29

标签: c# .net .net-core dotnet-httpclient

我想生成Http请求的内容,但实际上并不发出请求。我只想将其保存到磁盘。

这就是我的做法,我不是一个忠实的粉丝。目前,暂时仅登录到xUnit测试记录器。在没有实际执行请求的情况下是否有记录日志的更好方法?我不喜欢的最大部分是,我捕获请求的方法是格式化,实际上并不是在所有情况下都是正确的。

public async void GenerateWithHeader()
{
    using (MultipartFormDataContent content = GenerateMultipartContent())
    {
        HttpClient c = new HttpClient(new RequestCaptureHandler(new HttpClientHandler(), this.output));
        HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Post, "http://test.ca");

        //we want xml back
        msg.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml"));

        msg.Content = content;

        try
        {
            await c.SendAsync(msg);
        }
        catch (InvalidOperationException)
        {
            //suppress it.  we don't actually want to make the request
        }
    }
}

public class RequestCaptureHandler : DelegatingHandler
{
    private readonly ITestOutputHelper output;
    public RequestCaptureHandler(HttpMessageHandler innerHandler, ITestOutputHelper output)
        : base(innerHandler)
    {
        this.output = output;
    }

    protected override async System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        //The Request-Line begins with a method token, followed by the Request-URI and the protocol version, and ending with CRLF.The elements are separated by space characters.
        //Request-Line = Method <space> Request-URI <space> HTTP-Version CRLF
        this.output.WriteLine($"{request.Method} {request.RequestUri.ToString()} {request.Version}");

        //Zero or more header (General|Request|Entity) fields followed by CRLF
        foreach (var h in request.Headers)
        {
            this.output.WriteLine($"{h.Key}: {string.Join(' ', h.Value)}");
        }
                
        foreach (var h in request.Content.Headers)
        {
            this.output.WriteLine($"{h.Key}: {string.Join(' ', h.Value)}");
        }

        //An empty line (i.e., a line with nothing preceding the CRLF)  indicating the end of the header fields
        this.output.WriteLine("");

        //Optionally a message-body
        if (request.Content != null)
        {
            this.output.WriteLine(await request.Content.ReadAsStringAsync());
        }

        //Don't actually want to make the request.  This will cause an InvalidOperationException when the SendAsync function of HttpClient is called.
        return null;
    }
}

0 个答案:

没有答案