This is from a mail I sent to the Gemini mailing list on July 3, 2020, slightly edited.

The same mail in the list archive

Hi all

People on the IRC channel asked me to send an email to the list regarding the Titan protocol I've been using for my Gemini wiki project.

Background

I'm really interested in wikis. They seem to me to be the simplest form of collaboration in text. Simple both in because you don't need a lot of technology to make it work, and also simple because all of the structure, all of the processes, are things that the software doesn't provide: it's up to people to organize themselves. I wrote a bit more about it on my site, if you're interested.

2020-06-15 Why Wiki‽

At first, I proposed something I called Gemini+Write, and implemented it for my site, and for a Gemini Client I was using. It was inspired by my idea for Gopher Wiki. I know, I know. I keep bashing on that wiki idea. Anyway, the idea is simple: to read from a site, you open a connection and send a selector. To write, you open a connection and send a selector, and then, on subsequent lines, you send more stuff like MIME-type, file-size, password, and so on. It wasn't pretty.

2017-12-30 Gopher Wiki

2020-06-04 Gemini Upload

In any case, Sean Conner picked up on the idea, and started a long thread back in June. It went a lot further than what I had in mind, mimicking HTTP methods (GET, PUT, POST), discussed the differences between PUT and POST, and some form of authentication that used client certificates to allow users to edit just their pages.

2020-06-13 Uploading Gemini content by Sean Conner

2020-06-14 Uploading Gemini content by Sean Conner

Matthew Greybosch proposed to name this protocol "Titan" in one of the replies to Sean Conner's post.

2020-06-13 Uploading Gemini content by Matthew Graybosch

There was some resistance to the idea, and my mail setup was apparently causing some users a bit of grief, and for both of these reasons I didn't get involved in the discussion. I wanted to get a Gemini wiki working and that was all I cared about.

Titan

Sean Conner's Titan proposal had some ideas I liked and some I didn't care for. The shortest summary is the following, from the second thread link of his:

titan://example.com/post-handler/endpoint?size=1234&mime=text/plain
titan://example.com/path/to/new/resource;size=1234&mime=text/plain
titan://example.com/path/to/remove;size=0

The logic goes something like this [2]:

if the request has a query, it's an upload of data---accept data.
if the request has no query, and the path parameter (marked by ';')
  doesn't exist---error.
if the request has no query, and the path parameter exists:
  if size==0, delete the resource
  if size>0, accept data and make the resource available.

I decided that what I really needed was just the second example he provided:

titan://example.com/path/to/new/resource;size=1234&mime=text/plain

I also needed some form of authorization (are you allowed to edit the site) and I didn't really care for authentication (are you the person you claim to be). I imagined my Gemini wiki working without necessarily identifying users. I needed some sort of token, a kind of password. My Oddmuse wiki uses this system since 2003: there are editor and admin passwords, and knowing one of these passwords allows you to do things reserved to editors and admins, but these passwords aren't tied to usernames. They're basically just tokens. You can pass them to a friend and say: here, join us!

Thus, for my needs I need the following:

titan://example.com/path/to/new/resource;size=1234;mime=text/plain;token=hello

Some people used to web URIs might be wondering: where is the question mark between path and query? The point is that this isn't a query. If you look at the URI RFC 3986 section 3.3, you'll see what I mean:

"URI producing applications often use the reserved characters allowed in a segment to delimit scheme-specific or dereference-handler-specific subcomponents. For example, the semicolon (";") and equals ("=") reserved characters are often used to delimit parameters and parameter values applicable to that segment. The comma (",") reserved character is often used for similar purposes. For example, one URI producer might use a segment such as "name;v=1.1" to indicate a reference to version 1.1 of "name", whereas another might use a segment such as "name,1.1" to indicate the same. Parameter types may be defined by scheme-specific semantics, but in most cases the syntax of a parameter is specific to the implementation of the URI's dereferencing algorithm."

RFC 3986 section 3.3

So that's how I think about it. Let's look at this example again:

titan://example.com/path/to/new/resource;size=1234;mime=text/plain;token=hello

We want to create a new revision of "resource" and the necessary parameters, as defined by the Titan protocol, are size, MIME-type, and token.

Now, you might wonder: why size? The server needs to know when the transmission of the client ends. Remember, if connectivity is bad, content can arrive in chunks interspersed with silence. Is the client done? In text based transmissions, we have more options. A Ctrl-D might be used to indicate the end-of-file (EOF). In your ASCII man page it might say "EOT (end of transmission)". In very old tools like Berkley mail you'd end your letter with a single dot on a line. The Gopher spec also says that a single dot on a line ends the transmission. All of these solutions won't work when we're talking about binary files, however. And yes, I want a wiki where people can upload images, or audio files, or videos, PDF files. Therefore, no particular byte or pattern can be used. We need to tell the server how many bytes to expect, and then the server reads exactly that many bytes, with a timeout in case the transmission just isn't going to work.

You might also wonder: why MIME-type? Can't we just rely on file name extensions? I guess we could. But why not use MIME-types? I've gotten used to them. My wiki serves images called "foo" and tells your browser via the MIME-type that it's an image/png. It allows my wiki to store this MIME-type and serve it back in a response when clients request a file. Otherwise I'd have to guess. I've had unhappy experiences with /etc/mailcap files. All the programming languages do "something", merging system mailcap files with user mailcap files and programming language libary mailcap files, and mailcap files so much more than just an association of file name extensions and MIME-types. They're a nightmare. Compared to that complexity (which is often invisible to developers, granted), I find explicit MIME-types easier to deal with.

Upload

OK, so now we've talked about the request: The client sends titan://example.com/path/to/new/resource;size=1234;mime=text/plain;token=hello followed by the CR LF sequence we all know, and then it sends the 1234 bytes it promised to send. That's it.

Now, the client-server reaction can be a bit tricky if you're writing a client: how do you handle an error message after the first line? Because there will be errors. My wiki has errors for resources that aren't editable, sizes that exceed the max size I'm willing to accept, MIME-types I'm not willing to accept, and tokens that are not correct. There might be more. I'm using 59 error codes for them all. I know that Baschdel has been arguing for better error codes. The Baschdel proposal argued for special error codes: ES for wrong size, EM for wrong MIME type, and E_ for whatever else. Baschdel also argued that it would be nice if a server replied with WR to say that it will in fact accept the upload. I confess, I didn't really care for that and decided to write a very simple implementation.

Baschdels spin on Gemini uploading

Request for Comments (RFC)

So there you have it. Uploading! Titan! 🚀🚀🎉😃

What do you think?

I'd love to see more clients supporting it. I have two independent implementations to show how it works, both for servers and clients, four in total:

My wiki uses a server code that interfaces with the underlying Oddmuse wiki engine to edit pages.

The homepage of Alex Schroeder

My Gemini wiki uses stand-alone code to just serve .gmi files as a wiki, allowing users to create new ones and to edit existing ones.

The source code repository for Phoebe

My two Bash functions "gemini" and "titan" allow a super simple interaction with Gemini (for reading) and Titan (for writing).

The source code repository for Gemini & Titan

I also love Emacs and so I wrote some code that allows me to edit wiki pages from Elpher.

The source code repository for Gemini Write

Anyway, let me know what you think. Let me know what you'd like to implement for your servers and clients and what you'd need to add or drop from this proposal.

Here's what I can see:

What else?

Hope to hear from you all,

Alex