Once upon a time it was popular to put a counter on your web page, to show how many people had visited the site before you. I thought it be more fun, and less bragging about how long the page has existed, if it just showed who’s reading it now.

As I mentioned in a previous post, I’m learning Rust. My teaching project has been to make this web widget that shows the current number of browsers that that have the page open.

You see this counter here on the blog in the top right.

The idea is pretty simple. Have some javascript open a websocket to a server, and stream down messages with the current count, as it changes. When a client connects or disconnects, inform all other clients of the new total.

This does mean that it needs to keep one TCP connection open per client, which may be too costly for some sites. Especially since I’m putting it behind an nginx, so the machine needs to keep 3x the state.

I’m not logging anything to disk, nor sharing anything between the clients except for the current count. It’s just an amusing publicly visible presence counter.

Actually, because it can go up or down, I should really call it a gauge instead of counter.

SNI multiplexing

I plan to move this to its own port, so that I can stop involving nginx. But I don’t have a dedicated IPv4 address to give to livecount, unfortunately. The downside to a nonstandard port, of course, is that there will be many corp firewalls and such that will block it.

Maybe I can find some nice SNI multiplexer solution, and pass the file descriptor on to livecount for its hostname, and nginx for everything else. But I also want it to work with encrypted SNI, so that may be tricky.

Oh well, that project is for another day.

Continued Rust thoughts

I really like how Rust works. Well, I guess I don’t know if everything is Rust, or also the Warp framework. But it gives an almost functional programming HTTP handler, where you don’t just call out to the extract the various parts of the request you’re interested in. Instead you tell the HTTP framework at callback register time what you want, and it shows up as a function argument to your handler.

The language will not tolerate sloppiness.

nginx config

location /livecount {
    proxy_pass  http://127.0.0.1:8000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Building & running

For reasons I go into elsewhere, I couldn’t just cargo build --release.

$ rustup target add x86_64-unknown-linux-musl
[…]
$ cargo build --release --target=x86_64-unknown-linux-musl
[…]
$ ./livecount -t sec -vvvvvv
[… lots of debug output]

The code

The code is here.