0

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

这是一个示例 Nancy 模块:

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)中出现异常:“System.ObjectDisposedException:'无法访问已处理的对象。'”看来流正在关闭(_state = FrameStreamState.Closed - https://github.com/aspnet/KestrelHttpServer/blob/rel/2.0.0/src/Microsoft.AspNetCore.Server.Kestrel.Core/Internal/Http/FrameResponseStream.cs)过早但我不知道找出为什么或我需要改变什么来解决它!

4

1 回答 1

0

您应该使用 ResponseContentRead 而不是 ResponseHeadersRead

HttpResponseMessage response = await httpClient.GetAsync(Request.Query["url"],
                HttpCompletionOption.ResponseContentRead, cancellationToken);
于 2018-10-16T07:27:47.190 回答