Чтобы только отменить/отклонить ответы WebAPI, превышающие заданный предел, я должен узнать размер возвращаемого содержимого. Однако следующая строка:Замыкание при вызове LoadIntoBufferAsync в DelegatingHandler
response.Content.LoadIntoBufferAsync()
, похоже, зашел в тупик позже в цикле ответа API. Размер определяется правильно, и обработчик выполняет штраф, но потом запрос ожидает навсегда.
Это метод SendAsync моего DelegatingHandler.
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken).ContinueWith(
task =>
{
HttpResponseMessage response = task.Result;
if (response.RequestMessage != null && response.RequestMessage.Headers.AcceptEncoding != null && response.RequestMessage.Headers.AcceptEncoding.Count > 0)
{
if (response.Content != null)
{
response.Content.LoadIntoBufferAsync(); // when I remove this line the request finishes, but then ContentLength = 0
if (response.Content.Headers.ContentLength > 4000)
{
string encodingType = GetEncodingType(response.RequestMessage.Headers.AcceptEncoding); // use deflate if possible
if (encodingType == "deflate" || encodingType == "gzip")
{
response.Content = new CompressedContent(response.Content, encodingType);
}
}
}
}
return response;
}, cancellationToken);
}
Я пробовал разные комбинации с Wait (..), ConfigureAwait (..) и ContinueWith (..). С синтаксисом async/await у меня была та же проблема.
EDIT: SerializeToStreamAsync из компрессора (отвечает за сжатие потока контента):
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
Stream compressedStream = null;
if (m_EncodingType == "gzip")
{
compressedStream = new GZipStream(stream, CompressionMode.Compress, true);
}
else if (m_EncodingType == "deflate")
{
compressedStream = new DeflateStream(stream, CompressionMode.Compress, true);
}
return m_OriginalContent.CopyToAsync(compressedStream).ContinueWith(task =>
{
if (compressedStream != null)
{
compressedStream.Dispose();
}
});
}
=> Apperently трубопровод нарушается, когда это вызывается после:
response.Content.LoadIntoBufferAsync()
Вызов либо одно из два только работают, поэтому их проблема должна быть проблемой при чтении/записи потока контента.
Ну, текущий вариант, безусловно, * неправильно *. Каждый раз, когда вы видите метод с именем, заканчивающимся 'Async', где возвращаемое значение игнорируется, оно должно вызывать сигналы тревоги. –
Я думаю, проблема в том, что в моем классе CompressedContent я снова переопределяю содержимое с помощью zipped-потока и таким образом каким-то образом содержимое становится испорченным. – Philipp