Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert HttpRequestBase to HttpRequestMessage, considering header names?

I am wrapping an HttpRequestBase as an HttpRequestMessage, which requires all the headers be copied over. But since HttpRequestMessage is particular about which headers apply to the request object vs. the Content object, the httpRequest.Headers.Add line below sometimes throws InvalidOperationException.

public static HttpRequestMessage AsHttpRequestMessage(this HttpRequestBase request) {
    Requires.NotNull(request, "request");

    var httpRequest = new HttpRequestMessage(new HttpMethod(request.HttpMethod), request.Url);
    foreach (string header in request.Headers) {
        httpRequest.Headers.Add(header, request.Headers.GetValues(header));
    }

    if (request.Form != null) {
        // Avoid a request message that will try to read the request stream twice for already parsed data.
        httpRequest.Content = new FormUrlEncodedContent(request.Form.AsKeyValuePairs());
    } else if (request.InputStream != null) {
        httpRequest.Content = new StreamContent(request.InputStream);
    }

    return httpRequest;
}

Obviously I'd like my code to not throw exceptions, but rather appropriately apply each header to the appropriate object. How can I predict this? Is there any method I can use to test the applicability of a header short of one that generates and catches exceptions?

like image 647
Andrew Arnott Avatar asked Mar 04 '13 19:03

Andrew Arnott


1 Answers

It turns out it's quite simple. This snippet comes heavily inspired from ASP.NET's own open sourced source code.

/// <summary>
/// Clones an <see cref="HttpWebRequest" /> in order to send it again.
/// </summary>
/// <param name="message">The message to set headers on.</param>
/// <param name="request">The request with headers to clone.</param>
internal static void CopyHeadersFrom(this HttpRequestMessage message, HttpRequestBase request) {
    Requires.NotNull(request, "request");
    Requires.NotNull(message, "message");

    foreach (string headerName in request.Headers) {
        string[] headerValues = request.Headers.GetValues(headerName);
        if (!message.Headers.TryAddWithoutValidation(headerName, headerValues)) {
            message.Content.Headers.TryAddWithoutValidation(headerName, headerValues);
        }
    }
}
like image 62
Andrew Arnott Avatar answered Sep 28 '22 03:09

Andrew Arnott