uWebSockets.js icon indicating copy to clipboard operation
uWebSockets.js copied to clipboard

Experimental HTTP3

Open ghost opened this issue 3 years ago • 20 comments

There is now a HIGHLY experimental HTTP3 server built-in on x64 Linux binaries in unreleased binaries branch (npm install uNetworking/uWebSockets.js#binaries)

  • uWS.startQuicServer() launches a hello world server on port 9004 ipv6 ::1
  • It will not work if your localhost interface has no ipv6 address.
  • You can reach it by ./quiche-client --no-verify https://[::1]:9004/
  • I just remembered certs must lie in /home/alexhultman/uWebSockets.js/misc folder, so until I fix this nobody but me can run it 😉 But this will be fixed soon.
  • This function is obviously just a smoke test and will be replaced with proper uWS.QuicApp interfaces!

ghost avatar May 13 '22 02:05 ghost

You may be interested to have autotests and relative results of other servers, here is a ready-made solution https://interop.seemann.io/

P.S. By last spec recommend not to use the word QUIC in high level interfaces, recommend instead H3 and WebTransport )

uasan avatar May 13 '22 11:05 uasan

uWS::H3App is good

ghost avatar May 15 '22 02:05 ghost

https://github.com/uNetworking/uWebSockets.js/blob/master/examples/H3lloWorld.js

This example works and is programmable. I just need to fix the hardcoded cert paths, port and localhost address then it should be testable by others.

ghost avatar May 15 '22 17:05 ghost

Doing so, means you’ll be able to swap from uWS.App to uWS.H3App without changing any of your business logic — uWebSockets.js exposes HTTP/3 under the same very interface as it does HTTP/1.1.

Sounds cool for businessmen, but I'm an engineer and I doubt that compatibility will be 100%, but the goals are correct )

uasan avatar May 15 '22 21:05 uasan

Server pushes are only allowed to happen if the client side has agreed to them. In HTTP/3 the client even sets a limit for how many pushes it accepts by informing the server what the max push stream ID is. Going over that limit will cause a connection error.

Since you still need to handle a failed push, and the fact pushes are merely optimization attempts, you can have the same interface for http 1, only that those pushes always fails

ghost avatar May 16 '22 01:05 ghost

This is the same idea about making quic and TCP the same interface in uSockets; you just need to introduce the concept of streams inside connections, only that a TCP connection has a maximum of 1 stream.

Over generalization like this will allow everything to be more or less identical across all transports

ghost avatar May 16 '22 01:05 ghost

uWS is primarily interested in a high-performance implementation of websocket, H3 is interesting in a possible implementation of WebTransport, my doubts were about the possibility of making a backward compatible websocket interface with WebTransport.

uasan avatar May 16 '22 08:05 uasan

I don't agree. I think the killer demo/feature would be to make a standalone proxy that does WebSocket to WebTransport termination. A single binary you install with curl and run boom now you can test WebTransport. And when people feel like they want to invest more they use the server library directly

ghost avatar May 17 '22 15:05 ghost

People want simplicity and familiarity, and they want to hit the ground running.

ghost avatar May 17 '22 15:05 ghost

@alexhultman does the experimental http3 work include support for WebTransport that we can test, or is that yet to be implemented?

hpx7 avatar Jun 12 '22 03:06 hpx7

No but it will be very interesting to benchmark it when it becomes a standard.

ghost avatar Jun 12 '22 03:06 ghost

Do you know where to track progress of WebTransport becoming a standard? I saw that HTTP/3 just became a standard but not sure about WebTransport

hpx7 avatar Jun 12 '22 03:06 hpx7

No I'm also wondering. WebTransport is a tiny layer above Http3 so maybe it will land soon?

ghost avatar Jun 12 '22 03:06 ghost

WebTransport client has been available in Chrome Stable since v97 Jan 4 2022, you can open a console and use it right now. It needs a easy to use server preferably JavaScript, that would have large demand for those who need it. Not everyone needs it and WebSocket is a good easy option, if you have lots of streams and need low latency WebTransport is good

const wt = new WebTransport(url);

e3dio avatar Jun 12 '22 03:06 e3dio

Yep but it's still a draft. And I'm still wondering how popular services like Cloudflare will support it. Until all that is figured out there's no reason to rush

ghost avatar Jun 12 '22 03:06 ghost

I expect Cloudflare to expose WebTransport as a proxy to WebSocket origin servers.

ghost avatar Jun 12 '22 03:06 ghost

Below is quick reference to the WebTransport browser client API:

const wt = new WebTransport(url);

// Datagram read
for await (const data of wt.datagrams.readable) { /* datagram message */ }

// Datagram write
const writer = wt.datagrams.writable.getWriter();
writer.write(data);

// Incoming Uni-Directional Streams
for await (const stream of wt.incomingUnidirectionalStreams) {
   for await (const chunk of stream) { /* stream chunk */ }
}

// Create Uni-Directional Streams
const stream = await wt.createUnidirectionalStream();
const writer = stream.getWriter();
writer.write(data);

// Incoming Bi-Directional Streams
for await (const duplexStream of wt.incomingBidirectionalStreams) {
   // read
   for await (const chunk of duplexStream.readable) { /* stream chunk */ }
   // write
   const writer = duplexStream.writable.getWriter(); writer.write(data);
}

// Create Bi-Directional Streams
const duplexStream = await wt.createBidirectionalStream();
// read
for await (const chunk of duplexStream.readable) { /* stream chunk */ }
// write
const writer = duplexStream.writable.getWriter(); writer.write(data);

The server API could look like anything, here is potential mockup:

// App options, Incoming Streams and Datagram messages 
app.wt('/', {
   open: (wt) => {}, // new WebTransport connection
   datagram: (wt, arrayBuffer) => {}, // incoming datagram message
   stream: (wt, stream) => {}, // new incoming Bi or Uni directional stream
   close: (wt, code) => {}, // wt closed
});

// Stream methods
stream.write(data);
stream.subscribe(topic);
stream.onData(arrayBuffer => {});
stream.onClose(code => {});
stream.close(code);

// WT methods
wt.datagram(data);
wt.subscribeDatagram(topic);
stream = wt.stream(options);
wt.close(code);

// App methods
app.publishDatagram(topic, data);
app.publishStream(topic, data);

e3dio avatar Jun 14 '22 04:06 e3dio

I've taken a look at WebTransport in lsquic and looked at the draft. This will need support in lsquic, it's not possible to implement WT without inherent support in lsquic.

ghost avatar Jun 14 '22 07:06 ghost

Link to track the status of the development of WebTransport in Safari https://github.com/WebKit/standards-positions/issues/18

uasan avatar Jul 07 '22 13:07 uasan