Коа SSE соединение переподключение - PullRequest
0 голосов
/ 14 ноября 2018

Я установил соединение SSE с использованием Koa следующим образом:

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

// Sets up the HTTP header and sends a message via SSE
function writeSSE(ctx, message) {
  ctx.res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    Connection: 'keep-alive',
    'Access-Control-Allow-Origin': '*',
  });

  ctx.res.write(`id: 01\n`);
  ctx.res.write(`data: ${message}\n\n`);
}

// Router Middleware
router.get('/stream', (ctx, next) => {
  writeSSE(ctx, 'Stream reached.');
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(8080);

Где мои компоненты React запускают соединение следующим образом:

new EventSource("http://localhost:8080/stream")

Затем компонент получает отправленный ответс помощью метода writeSSE на сервере.

Но по какой-то причине конечная точка /stream достигается каждые 3 секунды или около того, как если бы соединение восстанавливалось.

А мой прослушиватель ошибок на внешнем интерфейсе каждый раз перехватывает СОЕДИНИТЕЛЬНОЕ событие.

this.state.source.onerror = (e) => {         
   if (e.target.readyState == EventSource.CONNECTING) {
     console.log("Connecting...");
   }
};

А на внутреннем уровне ctx.response равно { status: 404, message: 'Not Found', header: {} }.

БудетКто-нибудь знает причину этой проблемы?Это связано с тем, как я использую Коа?

Ответы [ 2 ]

0 голосов
/ 20 марта 2019

это слишком поздно, но я напишу свой опыт работы с sse с использованием Koa.

  • Прежде всего, использование ctx.res напрямую не очень ценится Koa, если вывсе еще хотите использовать его, убедитесь, что поставили ctx.respond = false, чтобы обойти механизм ответа коа.

  • По моему опыту, поток - лучший способ использовать SSE с Koa, вы можете сделать что-то вроде:

const stream = require('stream');
const koa = require('koa');


const app = new koa();

app.use(async ctx => {
  ctx.set({
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
    });
  ctx.status = 200;
  const stream = new stream.PassThrough()
  ctx.body = stream; // here koa will pipe the ctx.res to stream and end the ctx.res when ever the stream ends.
  let counter = 5;
  const t = setInterval(() => {
    stream.write(`data: hi from koa sse ${counter}`);
    counter--;
    if (counter === 0) {
        stream.end();
      clearInterval(t);
    }
  }, 1000);
});

Надеюсь, что эту помощь кто-нибудь сыграет с SSE на koa.

PS: Я написал это на скорую руку, если что-то не так с кодом, скажите мне, и яисправлю это.

0 голосов
/ 29 декабря 2018

Я нахожусь в процессе внедрения сервера на основе Koa для SSE.Я сталкивался с той же проблемой, и вот мои мысли / рабочее решение:

Насколько я могу судить, причина, по которой onmessage и onerror продолжают вызываться, заключается в том, что объект EventSource на стороне клиентаиспускает событие ошибки.Это приводит к разрыву соединения, в результате чего клиент отправляет другой запрос на инициализацию потока на сервер.Отсюда процесс повторяется бесконечно.

На основании моего собственного тестирования EventSource выдает ошибку из-за данных, которые отправляются обратно с сервера.В соответствии с docs ответ 200, имеющий тип контента, отличный от 'text / event-stream', вызовет ошибку.

В вашем примере вы объявили свой ответ как 'text / event-stream 'и передают строку в метод ctx.res.write.Хотя это выглядит правильно и фактически работает при использовании сопоставимого кода и Express, похоже, что это не работает в Koa.Однако, если вы измените «данные», которые вы записываете в свой ответ потоку, например, в этом примере здесь , вы обнаружите, что соединение установлено правильно.

Возможно, попробуйтеследующее:

//require Passthrough
const PassThrough = require('stream').PassThrough;

//then, in your writeSSE function, try this:
let stream = new PassThrough();
stream.write(`data: ${message}\n\n`);
ctx.res.write(stream);

Я не уверен на 100%, почему это изменение работает.Мое лучшее предположение состоит в том, что в объекте Koa ctx есть что-то, что препятствует тому, чтобы обычная строка или литерал шаблона рассматривались как допустимые данные текста / потока событий, но это полностью предположение (это вызывает вопрос о том, почему он работает в Express,но, надеюсь, кто-то более знающий может ответить на это для нас обоих).Из того, что я видел в других фрагментах, опубликованных в Интернете, в Koa можно использовать потоковый подход.

Я не уверен, каковы будут ваши результаты, так как похоже, что вы используете другойверсия Коа, чем я, но я бы дал ему шанс.Я смог правильно установить соединение, сделав это небольшое изменение.

...