[swift-server-dev] Prototype of the discussed HTTP API Spec

Helge Heß me at helgehess.eu
Wed May 31 09:39:35 CDT 2017

On 31 May 2017, at 16:07, Johannes Weiss <johannesweiss at apple.com> wrote:
>> Sorry if this is a little off-topic, but I just wanted to mention that I think neither is really true.
>> I’m not completely sure, but I think the Node.js HTTP implementation actually runs on multiple threads, it is just the user level JavaScript stack that is single threaded (I think it sparks CPU-count threads). May be wrong on that ;-)
> https://www.quora.com/Is-Node-js-single-threaded

Well, yes. This doesn’t discuss what I was talking about. What I think (but I may be wrong) is that Node.js (the kernel, not the JS API) may run multiple HTTP threads where sockets are accepted, headers parsed etc, before those are handed over to the JavaScript thread. Or in other words, where those parts run multi-threaded (accepting, HTTP header parsing).

This makes some sense because doing all those things also takes time.

I said, I may be completely wrong here, it would make sense though :-)

> well, the basic API is similar I think

… yeah sorry, but no, the basic API is nothing like it … You completely ignore that IncomingMessage and ServerResponse themselves are full streams and generic event emitters with everything attached.

Even IncomingMessage is nothing like our HTTPRequestHead - our head is just an inactive struct whereas the IncomingMessage is an actual object. Representing the read stream, and the headers, and even state whether the headers has been sent or not.
I don’t think that this is necessarily a good design, but it is really different to what was proposed.

> and the IncomingMessage (HTTPRequestHead for us) has headers, http version and stuff but not the body.

IncomingMessage *is* the body stream. It is like

  class IncomingMessage : AsyncInputStream ( : ErrorEmitter : EventEmitter)

> Instead of returning a closure, you register a handler in the request à la
> --- SNIP ---
> request.on('data',function(message){
>    response.write(message);
> });
> request.on('end',function(){
>    response.end();
> });
> --- SNAP —

This is the old style ‘push’ stream API. And even that has more features than callbacks. In ‘modern’ (years old) Node you would do:

  request.on(‘readable’) {
    let block = request.read();
    … do stuff with it ...

but more usually you would pipe it somewhere,

  let file = fs.createWriteStream(“/tmp/filedump”)

or request.pipe(transform(func() { … })).pipe(file)

This is a great (and pretty quick) intro to streams:


> which is reasonably close to .. return .processBody ..

Not at all, it is a huge superset of that.

> don't you think? To me it looks quite straightforward to port a Node HTTP app to the proposal we're discussing.

Since it provides no streams nor piping I have a hard time seeing you port anything but the most trivial demo.

But yes, it can be used as a *basis* to layer a Node-like framework on top. I.e. I could write a Noze.io stream which reads from the Swift HTTP API.

This is what we should focus on: Make sure that the stuff can be used as a basis for more advanced stuff.

> But I do agree that we don't have streams. I thought about something like that but I thought that's too much just for HTTP. If we want to have a more general streaming mechanism, we should probably discuss that in the Transport/Networking meetings, no?

Well, HTTP sits on top of two byte streams. Which can be plain TCP sockets, or TLS, or a local domain socket, even UDP, why not read from files for testing purposes? In short, HTTP should technically sit on top of arbitrary streams.
It’s not utterly important (nor necessarily better for performance), but it would make a nicer architecture.

>> That is why I said since the beginning that I’m more interested in how the API for the body stream will look like (as this affects sockets as well as HTTP). Now we essentially get separate APIs for the same thing ...
> I do agree with you here. But the networking group basically hasn't happened yet so I was proposing something here as we happened to have an implementation that works.

Sure. In a way that really is something for Foundation anyways, IMO.

>> While I’d love to have a nice streaming framework like the one Node has built right into Swift, maybe just some extension of GCD channels would do (if you don’t want to go the full stream-everything approach Noze.io does), but I understand that this is a little out of scope and probably impossible to agree on ;-) Doesn’t matter too much as you can put adapters on top of the stuff.
> 👍


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 842 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <https://lists.swift.org/pipermail/swift-server-dev/attachments/20170531/d80910e1/attachment.sig>

More information about the swift-server-dev mailing list