šŸ’¾ Archived View for gemini.omarpolo.com ā€ŗ post ā€ŗ gemini-clojure.gmi captured on 2022-01-08 at 13:39:21. Gemini links have been rewritten to link to archived content

View Raw

More Information

ā¬…ļø Previous capture (2021-11-30)

āž”ļø Next capture (2022-06-03)

šŸš§ View Differences

-=-=-=-=-=-=-

ā†© back to the index

A Clojure library for Gemini

Written while listening to ā€œGood Advicesā€ by R.E.M..

Published: 2021-10-16

Tagged with:

#clojure

#gemini

Iā€™d like to announce ā€˜com.omarpolo/geminiā€™: a new clojure library to make Gemini requests.

com.omarpolo/gemini: A Clojure library to make Gemini requests

Itā€™s also available on clojars, so go download it! :D

background

I needed something to ping antenna when I publish things on this blog. The site is assembled using some clojure scripts (not the most idiomatic clojure youā€™d read, but it works) and Iā€™m already shelling out to rsync for the upload. To ping antenna I wanted to do something natively.

Gemini is a simple protocol, isnā€™t it? Writing something from scratch should be simple, right?

the making of

It wasnā€™t simple, at least for me. I kinda get sleepy when I have to dig into the Java stdlib to learn how to do things. And I donā€™t know how to do networking at all in java, so there was a lot that I needed to learn.

I ended up writing a Java class, not because itā€™s required but because itā€™s easier. It exposes a really simple and barebone APIs to make Gemini requests and then wrote a more idiomatic (I hope) clojure wrapper around.

Speaking of Java, disabling the certificate validation wasnā€™t exactly straightforward (you need to provide your own X509ExtendedTrustManager) and quite surprisingly it doesnā€™t do SNI by default.

The magic spell to force a SSLSocket to do SNI is to

var params = new SSLParameters();
params.setServerNames(Collections.singletonList(new SNIHostName(host)))

/* ā€¦ */

var socket = ā€¦;
socket.setSSLParameters(params);

I was able to contribute back the same trick to jgemini, a Java graphical Gemini browser.

jgemini: A Java-based graphical browser for the Gemini protocol

The API

The main function is ā€˜fetchā€™. It takes a map and return a map. So clojure-ish.

The feature list is pretty short honestly:

and thereā€™s a major drawback: the ā€˜closeā€™ function must be called to clean things up. Thereā€™s a ā€˜with-requestā€™ macro (similar to ā€˜with-openā€™) that should help.

Itā€™s easy to stream a request since Iā€™m exporting the BufferedReader to clojure clients, you can just read from it. In combo with my gemtext library, itā€™s possible to stream text/gemini!

com.omarpolo/gemtext: text/gemini for clojure/clojurescript

The future

Gemini is simple, so there isnā€™t very much more to do. I planning to provide a function to control the certificates, so that one can implement TOFU on top of this library, but thatā€™s that.

Iā€™m still not completely happy of the provided APIs, but they doesnā€™t seem too bad and I donā€™t have a clue on how to improve them. Iā€™m open to suggestions thought ;)

-- text: CC-BY-SA-4.0; code: public domain unless specified otherwise

For comments, write at < blog at omarpolo dot com > or @op@bsd.network in the fediverse.

Capsule proudly assembled with Clojure