1
0
mirror of https://git.sr.ht/~adnano/go-gemini synced 2024-11-10 04:41:38 +01:00
Go implementation of the Gemini protocol
Go to file
2020-09-28 00:03:42 -04:00
examples Only generate certificates after CertificateRequired 2020-09-27 23:58:45 -04:00
.gitignore Implement certificate creation 2020-09-27 13:50:48 -04:00
cert.go Generate certificates on demand 2020-09-27 23:49:41 -04:00
client.go Return certificate if it exists in the store 2020-09-28 00:03:42 -04:00
gemini_test.go Change package name to gmi 2020-09-27 20:20:59 -04:00
gemini.go Directly initialize DefaultClient 2020-09-27 22:18:21 -04:00
go.mod Initial commit 2020-09-21 15:49:09 -04:00
LICENSE Temporarily allow common names in certificates 2020-09-27 15:57:55 -04:00
README.md Fix README.md 2020-09-27 21:40:51 -04:00
server.go Clarify comment 2020-09-27 22:13:50 -04:00
tofu.go Remove tilde from comment 2020-09-27 22:19:24 -04:00
verify.go Change package name to gmi 2020-09-27 20:20:59 -04:00

go-gemini

GoDoc

go-gemini implements the Gemini protocol in Go.

It aims to provide an API similar to that of net/http to make it easy to develop Gemini clients and servers.

Examples

There are a few examples provided in the examples directory. Some examples might require you to generate TLS certificates.

To run the examples:

go run -tags=example ./examples/server

Overview

A quick overview of the Gemini protocol:

  1. Client opens connection
  2. Server accepts connection
  3. Client and server complete a TLS handshake
  4. Client validates server certificate
  5. Client sends request
  6. Server sends response header
  7. Server sends response body (only for successful responses)
  8. Server closes connection
  9. Client handles response

The way this is implemented in this package is like so:

  1. Client makes a request with NewRequest. The client then sends the request with (*Client).Send(*Request) (*Response, error). The client then determines whether to trust the certificate (see Trust On First Use).
  2. Server recieves the request and constructs a response. The server calls the Serve(*ResponseWriter, *Request) method on the Handler field. The handler writes the response. The server then closes the connection.
  3. Client recieves the response as a *Response. The client then handles the response.

Trust On First Use

go-gemini makes it easy to implement Trust On First Use in your clients.

The default client loads known hosts from $XDG_DATA_HOME/gemini/known_hosts. If that is all you need, you can simply use the top-level Send function:

// Send uses the default client, which will load the default list of known hosts.
req := gmi.NewRequest("gemini://example.com")
gmi.Send(req)

Clients can also load their own list of known hosts:

client := &gmi.Client{}
if err := client.KnownHosts.LoadFrom("path/to/my/known_hosts"); err != nil {
	log.Fatal(err)
}

Clients can then specify how to trust certificates in the TrustCertificate field:

client.TrustCertificate = func(hostname string, cert *x509.Certificate, knownHosts *gmi.KnownHosts) error {
	// If the certificate is in the known hosts list, allow the connection
	return knownHosts.Lookup(hostname, cert)
}

Advanced clients can prompt the user for what to do when encountering an unknown certificate. See examples/client for an example.

Client Authentication

Gemini takes advantage of client certificates for authentication.

See examples/auth for an example server which authenticates its users with a username and password, and uses their client certificate to remember sessions.