当原始请求具有Content时,如何克隆HttpRequestMessage

本文关键字:何克隆 HttpRequestMessage Content 原始 请求 | 更新日期: 2023-09-27 18:15:46

我正在尝试使用这个答案中概述的方法克隆一个请求:https://stackoverflow.com/a/18014515/406322

但是,如果原始请求具有内容,则会得到ObjectDisposedException。

如何可靠地克隆一个HttpRequestMessage?

当原始请求具有Content时,如何克隆HttpRequestMessage

这应该能奏效:

    public static async Task<HttpRequestMessage> CloneHttpRequestMessageAsync(HttpRequestMessage req)
    {
        HttpRequestMessage clone = new HttpRequestMessage(req.Method, req.RequestUri);
        // Copy the request's content (via a MemoryStream) into the cloned object
        var ms = new MemoryStream();
        if (req.Content != null)
        {
            await req.Content.CopyToAsync(ms).ConfigureAwait(false);
            ms.Position = 0;
            clone.Content = new StreamContent(ms);
            // Copy the content headers
            foreach (var h in req.Content.Headers)
                clone.Content.Headers.Add(h.Key, h.Value);
        }

        clone.Version = req.Version;
        foreach (KeyValuePair<string, object?> option in req.Options)
            clone.Options.Set(new HttpRequestOptionsKey<object?>(option.Key), option.Value);
        foreach (KeyValuePair<string, IEnumerable<string>> header in req.Headers)
            clone.Headers.TryAddWithoutValidation(header.Key, header.Value);
        return clone;
    }

如果你在内容上调用LoadIntoBufferAsync,你可以保证内容在HttpContent对象中被缓冲。剩下的唯一问题是读取流不会重置位置,所以你需要ReadAsStreamAsync并设置流位置= 0。

我的例子与Carlos展示的非常相似…

 private async Task<HttpResponseMessage> CloneResponseAsync(HttpResponseMessage response)
        {
            var newResponse = new HttpResponseMessage(response.StatusCode);
            var ms = new MemoryStream();
            foreach (var v in response.Headers) newResponse.Headers.TryAddWithoutValidation(v.Key, v.Value);
            if (response.Content != null)
            {
                await response.Content.CopyToAsync(ms).ConfigureAwait(false);
                ms.Position = 0;
                newResponse.Content = new StreamContent(ms);
                foreach (var v in response.Content.Headers) newResponse.Content.Headers.TryAddWithoutValidation(v.Key, v.Value);
            }
            return newResponse;
        }

' ' '

Carlos的答案与一些linq快捷键:

public static async Task<HttpRequestMessage> Clone(this HttpRequestMessage httpRequestMessage)
{
    HttpRequestMessage httpRequestMessageClone = new HttpRequestMessage(httpRequestMessage.Method, httpRequestMessage.RequestUri);
    if (httpRequestMessage.Content != null)
    {
        var ms = new MemoryStream();
        await httpRequestMessage.Content.CopyToAsync(ms);
        ms.Position = 0;
        httpRequestMessageClone.Content = new StreamContent(ms);
        httpRequestMessage.Content.Headers?.ToList().ForEach(header => httpRequestMessageClone.Content.Headers.Add(header.Key, header.Value));
    }
    httpRequestMessageClone.Version = httpRequestMessage.Version;
    httpRequestMessage.Properties.ToList().ForEach(props => httpRequestMessageClone.Properties.Add(props));
    httpRequestMessage.Headers.ToList().ForEach(header => httpRequestMessageClone.Headers.TryAddWithoutValidation(header.Key, header.Value));
    return httpRequestMessageClone;
}

.NET版本的更新版本>5 . net

public static async Task<HttpRequestMessage> Clone(this HttpRequestMessage request)
{
    var clone = new HttpRequestMessage(request.Method, request.RequestUri)
    {
        Version = request.Version
    };
    if (request.Content != null)
    {
        var ms = new MemoryStream();
        await request.Content.CopyToAsync(ms);
        ms.Position = 0;
        clone.Content = new StreamContent(ms);
        request.Content.Headers.ToList().ForEach(header => clone.Content.Headers.TryAddWithoutValidation(header.Key, header.Value));
    }
    request.Options.ForEach(option => clone.Options.TryAdd(option.Key, option.Value));
    request.Headers
        .ForEach(header => clone.Headers.TryAddWithoutValidation(header.Key, header.Value));
    return clone;
}