gpt4 book ai didi

c# - DelegatingHandler 解压缩 WebApi 中的传入请求

转载 作者:太空宇宙 更新时间:2023-11-03 10:59:22 27 4
gpt4 key购买 nike

在我的应用程序中,我们从客户端发送大小适中的数据包并接收大小适中的响应,因此我想在向上和返回的过程中实现一些压缩。

在回来的路上它很好,因为我可以依靠 IIS 的动态压缩来为我做这件事,但在回来的路上我发现了以下问题。

我有一个委托(delegate)处理程序,用于解压传入的请求:(此代码的大部分基于 Fabrik.Common ( https://github.com/benfoster/Fabrik.Common ) 的部分内容)

public class DecompressionHandler : DelegatingHandler
{
public Collection<ICompressor> Compressors;

public DecompressionHandler()
{
Compressors = new Collection<ICompressor> {new GZipCompressor(), new DeflateCompressor()};
}

protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (request.Content.Headers.ContentEncoding.IsntNullOrEmpty() && request.Content != null)
{
var encoding = request.Content.Headers.ContentEncoding.First();

var compressor = Compressors.FirstOrDefault(c => c.EncodingType.Equals(encoding, StringComparison.InvariantCultureIgnoreCase));

if (compressor != null)
{
request.Content = await DecompressContentAsync(request.Content, compressor).ConfigureAwait(true);
}
}

var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(true);

return response;
}

private static async Task<HttpContent> DecompressContentAsync(HttpContent compressedContent, ICompressor compressor)
{
using (compressedContent)
{
var decompressed = new MemoryStream();
await compressor.Decompress(await compressedContent.ReadAsStreamAsync(), decompressed).ConfigureAwait(true);

// set position back to 0 so it can be read again
decompressed.Position = 0;

var newContent = new StreamContent(decompressed);
// copy content type so we know how to load correct formatter
newContent.Headers.ContentType = compressedContent.Headers.ContentType;
return newContent;
}
}
}

public class DeflateCompressor : Compressor
{
private const string DeflateEncoding = "deflate";

public override string EncodingType
{
get { return DeflateEncoding; }
}

public override Stream CreateCompressionStream(Stream output)
{
return new DeflateStream(output, CompressionMode.Compress, leaveOpen: true);
}

public override Stream CreateDecompressionStream(Stream input)
{
return new DeflateStream(input, CompressionMode.Decompress, leaveOpen: true);
}
}
public abstract class Compressor : ICompressor
{
public abstract string EncodingType { get; }
public abstract Stream CreateCompressionStream(Stream output);
public abstract Stream CreateDecompressionStream(Stream input);

public virtual Task Compress(Stream source, Stream destination)
{
var compressed = CreateCompressionStream(destination);

return Pump(source, compressed)
.ContinueWith(task => compressed.Dispose());
}

public virtual Task Decompress(Stream source, Stream destination)
{
var decompressed = CreateDecompressionStream(source);

return Pump(decompressed, destination)
.ContinueWith(task => decompressed.Dispose());
}

protected virtual Task Pump(Stream input, Stream output)
{
return input.CopyToAsync(output);
}
}

public interface ICompressor
{
string EncodingType { get; }
Task Compress(Stream source, Stream destination);
Task Decompress(Stream source, Stream destination);
}

public class GZipCompressor : Compressor
{
private const string GZipEncoding = "gzip";

public override string EncodingType
{
get { return GZipEncoding; }
}

public override Stream CreateCompressionStream(Stream output)
{
return new GZipStream(output, CompressionMode.Compress, leaveOpen: true);
}

public override Stream CreateDecompressionStream(Stream input)
{
return new GZipStream(input, CompressionMode.Decompress, leaveOpen: true);
}
}

解压工作正常,我有我的 request.Content 填充结果是我的解压 JSON。

当我将它传递给 base.SendAsync 并且它到达我的 Controller 方法时,模型为空,而在我实现压缩之前它一切正常。

我读过,当你读取进来的内容流时,这是一次性的事情,但我认为将 request.content 设置为解压后的结果应该让它被再次读取?

最佳答案

我解决了这个问题。

这是我的 HTTPClient 实现中的一个错误,我已经从使用 PostAsJsonAsync 转移到 PostAsync 来执行压缩客户端,但没有添加 Content-Type header 来指定 application/json。

在客户端完成后,一切都按计划进行。

关于c# - DelegatingHandler 解压缩 WebApi 中的传入请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18263651/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com