Как перехватить запрос HttpClient без выполнения запроса

#c# #.net #.net-core #dotnet-httpclient

#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;
    }
}
  

Комментарии:

1. На самом деле довольно просто создать его самостоятельно. Структура http хорошо документирована и буквально содержит только новые строки с данными. Все, что вам нужно, это StringBuilder, использование клиента добавит гораздо больше накладных расходов, чем вам нужно. Кроме того, объекты client и request не предназначены для использования таким образом, хотя объект запроса может сериализоваться так, как вы хотите.

2. если вы хотите сохранять только запросы, а не выполнять, почему бы не сохранить сами объекты HttpRequestMessage ?. кстати, стоит отметить, что один и тот же экземпляр HttpRequestMessage не может быть отправлен несколько раз

3. Если вы намереваетесь проверить запрос только для целей отладки, я рекомендую использовать Fiddler telerik.com/fiddler и настройте свое приложение, чтобы использовать его в качестве прокси-сервера learn.microsoft.com/en-us/dotnet/framework/configure-apps /. … Если нет, вы можете реализовать другое веб-приложение и настроить это приложение на использование другого в качестве прокси, затем вы можете использовать новое веб-приложение для проверки необработанных запросов.

4. @Bakurits — HttpRequestMessage не включает строку запроса или заголовки запроса.