gemini

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package gemini implements a Gemini server and exposes an interface that should be familiar to the users of the `net/http` package.

Example (ReadWriteTimeouts)
package main

import (
	"crypto/tls"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/francescomari/gemini"
)

func main() {
	cert, err := tls.LoadX509KeyPair(os.Getenv("TLS_CERT"), os.Getenv("TLS_KEY"))
	if err != nil {
		panic(fmt.Sprintf("load X.509 key pair: %v", err))
	}

	listener, err := net.Listen("tcp", ":1965")
	if err != nil {
		panic(fmt.Sprintf("listen: %v", err))
	}

	handler := gemini.HandlerFunc(func(r *gemini.Request, w gemini.ResponseWriter) {
		fmt.Fprint(w, "=> https://github.com/francescomari/gemini Yet another Gemini server\r\n")
	})

	// Configure separate timeouts for read and write operations.

	server := gemini.Server{
		Cert:         cert,
		Handler:      handler,
		ReadTimeout:  2 * time.Second,
		WriteTimeout: 3 * time.Second,
	}

	if err := server.Serve(listener); err != nil {
		panic(fmt.Sprintf("serve: %v", err))
	}
}
Example (Run)
package main

import (
	"crypto/tls"
	"fmt"
	"net"
	"os"

	"github.com/francescomari/gemini"
)

func main() {
	cert, err := tls.LoadX509KeyPair(os.Getenv("TLS_CERT"), os.Getenv("TLS_KEY"))
	if err != nil {
		panic(fmt.Sprintf("load X.509 key pair: %v", err))
	}

	listener, err := net.Listen("tcp", ":1965")
	if err != nil {
		panic(fmt.Sprintf("listen: %v", err))
	}

	handler := gemini.HandlerFunc(func(r *gemini.Request, w gemini.ResponseWriter) {
		fmt.Fprint(w, "=> https://github.com/francescomari/gemini Yet another Gemini server\r\n")
	})

	server := gemini.Server{
		Cert:    cert,
		Handler: handler,
	}

	if err := server.Serve(listener); err != nil {
		panic(fmt.Sprintf("serve: %v", err))
	}
}
Example (Timeout)
package main

import (
	"crypto/tls"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/francescomari/gemini"
)

func main() {
	cert, err := tls.LoadX509KeyPair(os.Getenv("TLS_CERT"), os.Getenv("TLS_KEY"))
	if err != nil {
		panic(fmt.Sprintf("load X.509 key pair: %v", err))
	}

	listener, err := net.Listen("tcp", ":1965")
	if err != nil {
		panic(fmt.Sprintf("listen: %v", err))
	}

	handler := gemini.HandlerFunc(func(r *gemini.Request, w gemini.ResponseWriter) {
		fmt.Fprint(w, "=> https://github.com/francescomari/gemini Yet another Gemini server\r\n")
	})

	// Configure a single timeout for both read and write operations.

	server := gemini.Server{
		Cert:    cert,
		Handler: handler,
		Timeout: time.Second,
	}

	if err := server.Serve(listener); err != nil {
		panic(fmt.Sprintf("serve: %v", err))
	}
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Handler

type Handler interface {
	Handle(r *Request, w ResponseWriter)
}

Handler handles client requests and produces responses.

If a handler doesn't write a response header or response data, the server automatically sends a StatusSuccess response with media type "text/gemini" and no content.

While a handler should deal with its own panics, the server intercepts and swallows a panic thrown by a handler. Unless a response has already been sent to the client, a panic results in a StatusCGIError response.

type HandlerFunc

type HandlerFunc func(r *Request, w ResponseWriter)

HandlerFunc is an implementation of Handler using a plain function.

func (HandlerFunc) Handle

func (f HandlerFunc) Handle(r *Request, w ResponseWriter)

Handle implements Handler.

type Request

type Request struct {
	// The URL scheme. It's always "gemini".
	Scheme string
	// The URL host. It's never empty.
	Host string
	// The URL port. It can be zero if the request didn't specify a port, in
	// which case the client expects the default port for the gemini scheme
	// to be used.
	Port int
	// The URL path. It's never empty. If the client didn't include a path in
	// the request, or if the path normalizes to nothing, Path is /.
	//
	// Paths are normalized by removing single-dot components and resolving
	// double-dot components.
	//
	// A trailing / in the original URL path is preserved.
	Path string
	// The query component of the URL. It can be the empty string if not
	// provided.
	Query string
	// The client certificate. It can be nil if the client did not provide a
	// certificate.
	//
	// If the client provides a certificate, the server always validates the
	// not-before, not-after, and signature of the provided certificate.
	// Self-signed certificates are expected and encouraged.
	Cert *x509.Certificate
}

Request contains the URL requested by the client.

type ResponseWriter

type ResponseWriter interface {
	io.Writer

	// WriteHeader writes the response header.
	//
	// If response data is written without calling this method, WriteHeader is
	// automatically called with StatusSuccess and a media type
	// of "text/gemini".
	//
	// Calling this method multiple times, or calling this method after
	// response data is written, has no effect.
	//
	// WriteHeader panics if trying to generate a header that does not conform
	// to the specification. For example, StatusSuccess always requires a
	// media type, and StatusInputExpected a prompt.
	WriteHeader(statusCode StatusCode, meta string)
}

ResponseWriter generates the server response. A ResponseWriter can't be safely used by multiple goroutines.

type Server

type Server struct {
	// The server certificate. Self-signed certificates are supported and
	// encouraged. This field is mandatory.
	Cert tls.Certificate
	// The handler for requests sent to this server. If not provided, the
	// server responds with StatusNotFound to every request that would
	// otherwise be processed by the handler.
	Handler Handler
	// Timeout sets the timeout for each I/O operation performed while serving a
	// connection, be it a read or a write. If not specified, no timeout is set.
	Timeout time.Duration
	// ReadTimeout sets the timeout for each read operation performed while
	// serving a connection. If not specified, no read timeout is set. If both
	// Timeout and ReadTimeout are specified, ReadTimeout overrides Timeout.
	ReadTimeout time.Duration
	// WriteTimeout sets the timeout for each write operation performed while
	// serving a connection. If not specified, no write timeout is set. If both
	// Timeout and WriteTimeout are specified, WriteTimeout overrides Timeout.
	WriteTimeout time.Duration
}

Server is a Gemini server. A Server can be safely used by multiple goroutines.

func (*Server) Serve

func (s *Server) Serve(listener net.Listener) error

Serve serves Gemini clients connecting to this server. Serve blocks until accepting a connection fails. Before returning, Serve waits until every in-flight request is processed and returns the error returned by the listener. Serve always returns an error.

type StatusCode

type StatusCode int

StatusCode is one of the available status codes.

const (
	StatusInputExpected            StatusCode = 10
	StatusSensitiveInput           StatusCode = 11
	StatusSuccess                  StatusCode = 20
	StatusTemporaryRedirection     StatusCode = 30
	StatusPermanentRedirection     StatusCode = 31
	StatusTemporaryFailure         StatusCode = 40
	StatusServerUnavailable        StatusCode = 41
	StatusCGIError                 StatusCode = 42
	StatusProxyError               StatusCode = 43
	StatusSlowDown                 StatusCode = 44
	StatusPermanentFailure         StatusCode = 50
	StatusNotFound                 StatusCode = 51
	StatusGone                     StatusCode = 52
	StatusProxyRequestRefused      StatusCode = 53
	StatusBadRequest               StatusCode = 59
	StatusCertificateRequired      StatusCode = 60
	StatusCertificateNotAuthorized StatusCode = 61
	StatusCertificateNotValid      StatusCode = 62
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL