Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTML5 HTTP/2 SSE Transport Support #369

Open
ubergarm opened this issue Jul 26, 2016 · 12 comments
Open

HTML5 HTTP/2 SSE Transport Support #369

ubergarm opened this issue Jul 26, 2016 · 12 comments

Comments

@ubergarm
Copy link

ubergarm commented Jul 26, 2016

I love that Feathers builds out API endpoints for services with both REST and multiple websocket providers. It may be of interest to additionally support an HTTP/2 SSE transport provider.

http://docs.feathersjs.com/providers/

I searched for this issue but didn't find it yet despite it being mentioned 4 months ago on a hacker news discussion (referenced below).

Thanks!

https://hn.algolia.com/story/11290577/feathers-2-0-a-minimalist-real-time-javascript-framework

N nailer  - 4 months ago
> exposes both a RESTful and real-time API automatically through HTTP/HTTPS and over websockets.
Why not both at once with HTML5 SSE?

M Matthias247 - 4 months ago
I think SSE has two limitations that might not make it too useful for some scenarios:
- Each SSE channel would require a separate TCP connection. And as the connections for a browser are limited, you can not support a lot of of different SSE channels. This is mainly a HTTP/1.1 problem, HTTP/2 fixes this. But as browser and server support for HTTP/2 is still limited you might not bet on it.
- SSE can only send chunks of text in each notification, where the possible payload is additionally limited by the SSE encoding (you can't send text with <br /><br /> in it). So if you need binary or abritrary (JSON?) text objects you would need some additional encoding. Like object -> json string -> byte-array representation -> base64 string. This works, but the overhead for your application (must do the encoding) and the browser (must to all the decoding and look for the <br /><br />) is not ideal.
I'm currently experimenting with using HTTP/2 and fetch API with readable streams to stream arbitrary objects on a bigger number of parallel channels from server to client. This seems to work and looks quite promising for the future, but due to missing browser and partly also missing server support the solution is definitely in it's infancy.
So the current safe bet for enabling lots of notification channels or enabling realtime queries would still be websockets.

D daffl - 4 months ago
That sounds like something worth keeping track of. Do you want to create an issue at https://github.com/feathersjs/feathers/issues for it? The nice thing is that you most likely won't have to change your services when adding a new transport layer.
@daffl
Copy link
Member

daffl commented Aug 4, 2016

From what I could see, it does not seem as if Express will support HTTP2 any time soon so this will be very dependent on #258.

@ekryski
Copy link
Contributor

ekryski commented Aug 15, 2016

I did do some spelunking in this area a couple weeks back. I guess you can get it to work with Express5 but who knows what is going on with that branch. Here's an example from Stackoverflow.

There is also the spdy module which is great but I've heard is becoming deprecated in favour of a more strict http2 module.

Realistically, it definitely depends on #258 and likely not something that will happen in the very near term.

@bonesoul
Copy link

@daffl it's quite easy to implement a http2 server with: https://github.com/indutny/node-spdy

@ekryski
Copy link
Contributor

ekryski commented Nov 12, 2016

I had some discussion about this in Slack with @MichaelErmer. He's using Nginx like so:

docker(feathers)=>docker_volume(unixsocket)=>docker(nginx)

with Nginx handling http2. IMHO this might be the more appropriate way to do things and Feathers likely shouldn't care about HTTP2 directly with the following caveats:

  • Depending on how you handle authenticated http2 connections. Whether we have to do something similar to the way we are handling sockets
  • How you want to handle server push events (ie. does your feathers app still use sockets alongside http2 or do you use http2 for everything)

Barring those considerations it may or may not make sense to include HTTP2 as a transport. Still some more investigation to do....

@muloka
Copy link

muloka commented Sep 27, 2017

Restify is adding http/2 support restify/node-restify#1489

@zhakhalov
Copy link

zhakhalov commented Mar 6, 2018

I agree that using nginx Feathers shouldn't care about HTTP/2 it even more it may be mounted even without SSL but nevertheless here's my working example:

// at the the very bottom of the app.js

// Enable https server
const ssl = app.get('ssl'); // get ssl configurations from config.json
let server;

if (ssl) {
  server = spdy.createServer({
    key: fs.readFileSync(path.resolve(__dirname, ssl.key)),
    cert: fs.readFileSync(path.resolve(__dirname, ssl.cert)),
  }, app);
} else {
  server = spdy.createServer(app);
}

app.setup(server);

module.exports = { app, server };

// index.js
const { app, server } = require('./app');
const port = app.get('port');

// feathers-socketio explicitly creates http server
server.listen(port); // call `listen` on the server

daffl pushed a commit that referenced this issue Aug 29, 2018
* Logout should always give a response.

I'm not sure what the correct way to handle this is, but this fixes feathersjs-ecosystem/authentication-client#10.

* Make sure it’s a function before trying to call it

I somehow encountered a scenario where callback didn’t exist, so this catches it.  For some reason I can’t seem to test logging out when not logged in.
daffl pushed a commit that referenced this issue Aug 29, 2018
* Logout should always give a response.

I'm not sure what the correct way to handle this is, but this fixes feathersjs-ecosystem/authentication-client#10.

* Make sure it’s a function before trying to call it

I somehow encountered a scenario where callback didn’t exist, so this catches it.  For some reason I can’t seem to test logging out when not logged in.
@avimar
Copy link

avimar commented Jun 4, 2020

You can install spdy and use that as the server, as mentioned above: #369 (comment)

https://www.ssllabs.com/ssltest/analyze.html gave me the same A+ score for https vs spdy and all related notes- just some had a handshake of spdy or h2

@strarsis
Copy link

strarsis commented Mar 2, 2022

Is HTTP2 now supported in 2022? Can I implement a SSE source now with FeathersJS?
I also want to terminate HTTPS/HTTP2 using Traefik in front of the FeatherJS app.

@strarsis
Copy link

strarsis commented Mar 6, 2022

Yes, using a reverse proxy like Traefik in front of the FeathersJS app for HTTP/2 support alleviates the connection limit for SSE.
It should also bring basically all advantages of HTTP/2 (the connection between the FeathersJS app and Traefik is usually very, very fast and low-latency anyway).

@strarsis
Copy link

strarsis commented Mar 14, 2022

It is relatively simple to add SSE to a FeathersJS app - however, one thing I hadn't been able to solve is that the FeathersJS app hangs while the SSE request runs.

import { createSession, createChannel } from 'better-sse';
import { IncomingMessage, ServerResponse } from 'http';

export default function (app: any): void {
  const debugSseSource = require('debug')('sseSource');
  const sseChannel = createChannel();

  // Order creations
  const orders: any = app.service('orders'); // use endpoint URL

  app.get('/v1/admin/orders', async (req: IncomingMessage, res: ServerResponse) => {
    // on new connections, add SSE session to SSE channel
    const sseSession = await createSession(req, res);
    sseChannel.register(sseSession);
    debugSseSource('Client (orders) has joined.');
    //res.end(); // @TODO/PROBLEM without the whole FeathersJS app hangs - but it stops the request...
  });

  orders.on('created', (order: any) => {
    // broadcast to all clients
    debugSseSource('order created');
    sseChannel.broadcast(order, 'created');
  });
};

Related SO discussion: https://stackoverflow.com/a/71466957/4150808

@emeagenciadigital
Copy link

2023 any update ?

@strarsis
Copy link

strarsis commented Apr 7, 2023

+1, as SSE is ideal for notifications / browser push, even better so than web sockets.

I had a discussion on Discord about adding SSE natively, the concensus was that Websockets are a kind of functional superset of SSE. Maybe add a plugin package for FeathersJS that adds SSE?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants