I think I have ready everything I wanted to support in my Gemini server, at least on a first version that is “useful”. I may add more things later, perhaps experimenting with some ideas like server-side support for gemlogs.
This is the feature list:
- Static files, including optional directory listings.
- IPv4 and IPv6.
- Configurable MIME types, or a built-in resolver.
- Virtual hosting, with SNI support.
- User provided certificates or auto-generated in memory (for development).
- Configurable SSL engine (e.g. TLS 1.2 and/or TLS 1.3), with configurable ciphers.
Other than the virtual hosting with SNI support, there’s nothing too exciting.
Although I have already tests for the tricky parts, I still need to write some more to validate a few branches, and to have some regression protection moving forward.
But then I found this Gemini diagnostics repo created by the author of Jetforce Gemini server, as a torture test for Gemini servers.
And turns out, my server was passing all tests but two!
The first issue was related to returning a “not found” response when the request contained an invalid UTF-8 sequence, instead of “bad request”.
This was easy to fix: I was trusting Akka’s decode method, and it replaces
invalid sequences with the infamous �
. Then I was checking for a resource on
disk that obviously didn’t exist (hence the “not found” response).
The solution was to write my own decoder:
val charsetDecoder = Charset.forName("utf-8").newDecoder()
def decodeUTF8(value: ByteString): Either[Throwable, String] =
Try(charsetDecoder.decode(value.toByteBuffer).toString()).toEither
Very simple. I included it in the input validation, and that test now passes.
The other issue is related to the TLS implementation provided by Akka, that
doesn’t seem to provide a close_notify
TLS signal before closing the
connection.
I’m not a TLS expert, so I will investigate to see how important is this, what are the consequences, and if I can fix it or perhaps file a bug report to Akka.
So I’ll see to write some tests and I’m almost ready for a first release –that nobody will use, of course; look a Jetforce, it is very nice!–. I may deploy the service as well, and put some content on the Gemini space!