关于Krestrel的NancyFX - 响应流关闭

时间:2018-05-29 20:43:14

标签: nancy kestrel

我尝试制作一个简单的代理服务器,尝试从IP摄像机流回数据(IP摄像机不支持OPTIONS,还有一些其他问题!)。我尝试使用NancyFX和Krestrel使用以下代理模块执行此操作。我们的想法是获取1028个字节的数据并将其异步写入输出流,直到被取消。

以下是南希模块的示例:

using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Nancy;

namespace Server.Modules
{
    public class Proxy : NancyModule
    {
        public Proxy() : base("api/proxy")
        {
            Get("/", ProxyPage);
        }

        private async Task<Response> ProxyPage(dynamic args, CancellationToken cancellationToken)
        {
            // Create HttpClient
            using (var httpClient = new HttpClient()) // Make this global/cached and indexed by auth code
            {

                // Handle Authentication
                var auth = string.Empty;
                if (!string.IsNullOrEmpty(Request.Headers.Authorization) && Request.Headers.Authorization.Contains(" "))
                    auth = Request.Headers.Authorization.Split(' ')[1];
                else if (!string.IsNullOrEmpty(Request.Query.authorization))
                    auth = Request.Query.authorization;
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth);

                // Create Proxy REsponse object
                var proxyResponse = new Response();

                // Get Async
                HttpResponseMessage response = await httpClient.GetAsync(Request.Query["url"],
                    HttpCompletionOption.ResponseHeadersRead, cancellationToken);

                // Set Content Type
                proxyResponse.ContentType = response.Content.Headers.ContentType.ToString();

                // Set Status Code
                proxyResponse.StatusCode = (HttpStatusCode)(int)response.StatusCode;

                // Handle stream writing
                proxyResponse.Contents = async s =>
                {
                    var result = response.Content.ReadAsStreamAsync();
                    var data = new byte[1028];
                    int bytesRead;
                    while (!cancellationToken.IsCancellationRequested && (bytesRead = await result.Result.ReadAsync(data, 0, data.Length, cancellationToken)) > 0)
                    {
                        await s.WriteAsync(data, 0, bytesRead, cancellationToken);
                        await s.FlushAsync(cancellationToken);
                    }
                    response.Dispose();
                };

                // Return Response container
                return proxyResponse;
            }
        }
    }
}

当我运行它时,我经历了几次while循环,但在FrameResponseStream(Krestrel)中得到一个异常:&#34; System.ObjectDisposedException:&#39;无法访问已处置的对象。&#39; &#34;看来流已经过早关闭(_state = FrameStreamState.Closed - https://github.com/aspnet/KestrelHttpServer/blob/rel/2.0.0/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/FrameResponseStream.cs),但我无法弄清楚为什么或需要改变它来解决它!

1 个答案:

答案 0 :(得分:0)

您应该使用ResponseContentRead而不是ResponseHeadersRead

HttpResponseMessage response = await httpClient.GetAsync(Request.Query["url"],
                HttpCompletionOption.ResponseContentRead, cancellationToken);