3

Wondering how to setup a persistent connection between client and server in Node.js.

The persistent connection should be able to send requests back and forth from both sides. It seems like it needs to have a mechanism for delineating each request, such as \r\n if requests are JSON, but not sure what best-practices are here if it's already been done before. Wondering how web-sockets handle this.

Mozilla says Keep-Alive shouldn't be used in production, so wondering if that still holds with HTTP2.

With EventSource you can receive server events, but wondering if there is a way to add client events to send to the server.

In the end, I would like to have a simple setup for two-way communication like WebSockets, but am not sure of best practices in HTTP2 and if it should just be done with WebSockets. I would prefer to try to do this without websockets.

Lance
  • 75,200
  • 93
  • 289
  • 503
  • Why not use websockets? With a library such as socket.io or SockJS they can be built to support older platforms – pfg Dec 12 '17 at 19:23
  • Just want to learn how it works. – Lance Dec 12 '17 at 19:26
  • 1
    If you're looking for passing messages between applications, not on a web browser, then checkout [grpc](http://grpc.io). It gives you http2, and type-safe service definitions, and much more. – Adi Levin Dec 12 '17 at 20:51

1 Answers1

3

With all due respect, I believe you're under the mistaken assumption that the HTTP/2 connection is page specific.

In actuality, HTTP/2 connection are often browser wide connections. It's not possible for an HTTP/2 push to know which page/tab will use the data (possibly more than one).

Also, see the discussion here that includes a myriad number of reasons as to why HTTP/2 couldn't (or shouldn't) be used as a Websocket alternative.

On the other hand, if HTTP/2 is "promised" and Websockets are unavailable, than polling might be an option.

Polling with HTTP/2 will be significantly more resource friendly than polling with HTTP/1.1, even though it would still be far more expensive than Websocket push (or poll) due to the extra header and authentication data (it will also decrease security, but that's probably something nobody really cares about all that much).

P.S.

Websockets over HTTP/2

This is a non-issue unless HTTP/1.1 is retired (in fact, IMHO, this is intentional and good).

It's true that HTTP/2 connections can't be "upgraded" (changed) to Websocket connections, nor can they tunnel Websocket data, but that means absolutely nothing.

New Websocket connections use the existing HTTP/1.1 upgrade handshake and that's it.

Any HTTP/2 server that supports Websockets will support the handshake.

Keep-Alive

Mozilla warns against the non-standard Keep-Alive header. However, the Connection: keep-alive standard for HTTP/1.1 (which is also the default for HTTP/1.1 clients) is definitely recommended.

SSE (Server Sent Events)

SSE pre-date Websockets and they didn't get much traction in the community, while Websockets were adopted with a vengeance.

wondering if there is a way to add client events to send to the server

Simple - send an HTTP request. The reply can be asynchronously received with SSE.

I like Websockets better. As far as server-side goes, I find them easier to manage and code.

Myst
  • 18,516
  • 2
  • 45
  • 67
  • Websockets and HTTP/2 don’t mix well together and that is an issue if you want a site on HTTP/2 and including a websocket connection on the same domain. Currently that will not work so only option is to disable HTTP/2 for now or move the websocket connection to a different domain. Hopefully be sorted soon as websockets over HTTP/2 is well on the way to getting formally specced. – Barry Pollard Dec 13 '17 at 07:14
  • @BazzaDP , I think the issue you’re experiencing is server specific. HTTP/2 and Websockets can live happily on the same domain name, using the same backend application, with no issues at all. When the application server doesn’t support HTTP/2 (and it seems many don’t), this is easily achieved using a proxy web server, such as nginx, which forwards requests to the application server using HTTP/1.1 and can also be set up to respond directly to static file requests. This is a very common setup and most application servers run behind a proxy anyway, both for load balancing and TLS negotiations. – Myst Dec 13 '17 at 13:07
  • If you want to know which tab a message goes to over HTTP/2, you can just use the stream identifier, can't you? – sudo May 01 '18 at 01:14
  • @sudo I'm not sure I understand your comment. HTTP/2 connections are browser wide, they don't belong to any specific tab / window. AFAIK, the HTTP/2 `push` semantics can't be directed at a specific tab... how does a the ID help with that? – Myst May 01 '18 at 01:19
  • @sudo , Oh, thank you for explaining your question. The answer is no. The new `push` (or PUSH_PROMISE to be exact) doesn't include any information about the "related" stream ID. [The stream ID is totally new and unrelated to any previous request](http://httpwg.org/specs/rfc7540.html#PUSH_PROMISE). – Myst May 01 '18 at 01:21
  • @Myst Sorry, I edited from "random ID" to "stream ID" right after I asked. I realized I'm not familiar enough with how a client-side script in a webpage might tap into the existing HTTP/2 connection. If the stream ID won't help, I was thinking the server sends back a random ID with the webpage so a given tab can ignore inbound messages that don't use the random ID it got. – sudo May 01 '18 at 01:30
  • If you can't use the existing connection, I know you could have the webpage open new HTTP/2 connection to the server to get WebSockets-like functionality, as the gRPC client would do. – sudo May 01 '18 at 01:32
  • @sudo, this isn't possible with HTTP/2. As for gRPC, AFAIK, it's a different protocol (just like HTTP/2, but with some different semantics). [gRPC browser clients emulate gRPC functionality using different approaches](https://github.com/improbable-eng/grpc-web#browser-support) (such as AJAX, polling, etc'), each using a different HTTP/2 stream that is initiated by the browser (not HTTP/2 `push`). gRPC isn't designed for browsers, the web-client functionality uses HTTP/2 to bridge between the two protocols. When it comes to `push`, HTTP/2 push promise is very different than push notifications. – Myst May 01 '18 at 01:46