Skip to content

Instantly share code, notes, and snippets.

@johnwcowan
Last active January 17, 2021 21:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johnwcowan/d3211496ad89125c77297c6586ebe176 to your computer and use it in GitHub Desktop.
Save johnwcowan/d3211496ad89125c77297c6586ebe176 to your computer and use it in GitHub Desktop.
Dioscuri, a Gemini-adjacent protocol for interaction

This gist will be maintained, and supersedes all IRC and email description of Dioscuri.

Dioscuri, a Gemini-adjacent protocol for interaction

Dioscuri is a protocol intended to supplement Gemini for doing things like performing remote actions or running an application server. It is the POST to Gemini's GET. Dioscuri servers will run on a different port from Gemini servers, so that they do not interfere with each other; it will often be useful to run multiple servers on one host, so no fixed port is specified. The use of client certificates for authorization is strongly recommended, especially if requests are interpreted to affect server-side state.

The name "Dioscuri" is the Latin version of the Classical Greek name Διόσκουροι for the Heavenly Twins, Castor and Pollux/Polydeukes, who were called Gemini in Latin; the constellation is named after them. I say dee-OH-skoo-ree, but Greeks, classicists, and others should feel free to pronounce the name their way.

Great thanks to the members of #gemini, especially lukee and aravk, and to the members of the Gemini mailing list, especially meff and snan.

Alternatives to Dioscuri include Titan, which is for upload (the PUT to Gemini's GET), using the query part of an URL (the media type can't be specified and the length is highly limited), and inimeg, which starts out as a Gemini connection in which the client and server switch roles.

Client transmission

A Dioscuri request starts out with the client sending a single line, <URL><SP><MEDIA-TYPE><CR><LF>. This indicates that a body follows which should be interpreted according to the media type. For example, gemini://example.org/foo.gmi text/gemini means that the Dioscuri server should do something with the following body, which is of type text/gemini. This line is limited to 1024 characters including the terminating <CR><LF>. When no request body is required, by convention a Dioscuri client should use the media type inode/x-empty (which is used by the file command when asked to give the media type of an empty file). In that case no body follows.

The client ends the upload by closing the write side of its socket while leaving the read side open. This limits client languages to those having libraries that can do this.

Server transmission

When Dioscuri has received the request line and body, then it does whatever it does, depending on the server, the URL (which does not have to refer to an actually existing resource), and the media type. For example, sending a request line of:

  • gemini://example.org/foo.gmi text/gemini might replace the contents of foo.gmi with the uploaded body.
  • gemini://example.org/do/this text/javascript might cause the JavaScript in the uploaded body to be executed on the server.
  • gemini://example.org/arithmetic text/plain might evaluate an arithmetic expression in the body and return the result as text/plain.
  • gemini://example.org/widget-search application/json might ask the server to interpret the JSON body as a complex search request through an application server's list of widges and return another JSON body specifying the matching widgets.

All 2-digit status codes have the same meaning as in Gemini.

If the server has nothing to send to the client, as in the case of an upload it can respond with the media type inode/x-empty, which means that there is no response body.

External bodies

In some cases, the server may not wish to return a body, but rather return an URL where the body may be found. This is done by using the media type message/external-body; access-type=URL; URL="[url]" where [url] is replaced by the URL where the body is. (See RFC 2017 for details.) Note that this is not the same as a 30 status code, which means that the request should be retried at a different URL.

For example, a client wishes to add a new file to a container (directory or whatever) in the server but leaves it up to the server to choose the new URL according to some algorithm (random, timestamp, etc.) So a request of gemini://example.com/container text/gemini followed by the body could in such a case respond 20 message/external-body; access-type=URL; URL="gemini://example.com/container/20201220202020.gmi" meaning that the new resource can be found at gemini://example.com/container/20201220202020.gmi.

Internationalization

The protocol URLs used by both clients and servers are URIs; that is, ASCII-only. However, if a client or server obtains an IRI from a body or an external source such as a configuration file that it wishes to use as a protocol URL, it must convert it to an URL by Punycoding the host and then %-encoding all IRI reserved characters. Caution must be taken not to %-encode what is already %-encoded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment