NancyFX на Krestrel - поток ответов закрыт - PullRequest
0 голосов
/ 29 мая 2018

Я пытаюсь создать простой прокси-сервер, который будет пытаться передавать данные обратно с 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) преждевременно, но я не могу понять, почему или что мне нужно изменить, чтобы решить эту проблему!

1 Ответ

0 голосов
/ 16 октября 2018

Вы должны использовать ResponseContentRead вместо ResponseHeadersRead

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