-- Leo's gemini proxy

-- Connecting to circadian.gemlog.org:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

Serving Gemini In Dart


When I said I’d try serving Gemini using Dart, I figured it was at least a half-day project. It turned out to be more like five minutes.


Code Reuse


The reason, of course, was that someone has done it already:


package:gemini_server


And so a minimal Dart server is just this:


import 'dart:convert';
import 'dart:io';

import 'package:gemini_server/gemini_server.dart';

Future<Response> handler(Request request) async =>
    // TODO: canonicalize and check request path before serving!
    Response(
      statusCode: StatusCode.success,
      meta: 'text/gemini',
      body: utf8.encode(File('root${request.uri.path}').readAsStringSync()),
    );

void main() async {
  final context = SecurityContext()
    ..useCertificateChain('<pem file>')
    ..usePrivateKey('<pem file>');

  await GeminiServer.bind(
    address: InternetAddress.anyIPv4,
    port: 1965,
    context: context,
    callback: handler,
  );
}

Of course a bit more code than this is needed to handle different mime types, serving only from under the desired root and missing files; but, you get the idea.


Certificates


The biggest difficult I had in switching from `agate`, which I had been using, to Dart, was simply converting the certificates that `agate` had auto-generated. After some head scratching the magic invocations turned out to be:


openssl x509 -inform der -in cert.der -out cert.pem
openssl pkey -in key.der -out key.pem

One Click Feedback


The one feature I wanted from my custom server was a way to offer a “one click feedback” mechanism; a way to approximately measure how many people read and liked a post.


Not having seen something like this in gemspace so far, I simply rolled my own:


I added an `action` folder, forbidden to crawlers in `robots.txt`, where the feedback interaction can happen; a feedback URL is for example `action/thanks/gemlog/serving-gemini-in-dart.gmi` for this post.

I wrote handlers that log feedback and redirect to a “thanks for the feedback” page.

And, I tweaked my `gmi` handler to add the same feedback links to the end of every gemlog entry.


I experimented with the “UI” added at the end of gemlog entries, settling on something that I hope is as simple as possible but no simpler.


Of course, gemlogs are supposed to be low pressure places away from the bustle of “likes” and other monstrosities of the web; having just created a monster, I hope I then hobbled it sufficiently by not publishing “like” counts at all, anywhere. They are just something I can check for a little guidance on what to write or post next.


Conclusion


We’ll see. I like having a custom server; I also made it apply my


Typography Fixes


directly when serving `gmi` files so I don’t have to remember to batch update them; and will likely do the same with the index and feed. Coding is fun!


Feedback 📮

👍 Thanks!

👎 Not for me.

🤷 No opinion.

Comments.


So far today, 2024-05-13, feedback has been received 2 times. Of these, 0 were likely from bots, and 2 might have been from real people. Thank you, maybe-real people!


   ———
 /     \   i a
| C   a \ D   n |
   irc   \     /
           ———

-- Response ended

-- Page fetched on Mon May 13 17:28:25 2024