gemini

package module
v0.0.0-...-436d3e5 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 2024 License: ISC Imports: 13 Imported by: 7

README

go-gemini

Go Reference

go-gemini is a library that provides an easy interface to create client and servers that speak the Gemini protocol.

Spec version supported: v0.16.0, November 14th 2021

This version of the library was forked from ~yotam/go-gemini to add additional features, as well as update it to support newer specs. At the time of forking, it had not seen any new commit for 5 months, and was based on v0.9.2.

The server part of this library has been removed. I don't use it and don't want to maintain it.

This is mostly a personal library. You might want to check out go-gemini (no relation) for more features.

Project Status

go-gemini is in maintenance mode. Bug and spec fixes only. See my blog post for details.

Improvements

This fork of the library improves on the original in several ways, some listed above already.

  • Client supports self-signed certs sent by the server, but still has other checks like expiry date and hostname
    • The original library could only work with self-signed certs by disabling all security.
  • Invalid status code numbers raise an error
  • Set default port and scheme for client requests
  • Raise error when META strings are too long in the response header
  • Supports new status code updates
  • If SSLKEYLOGFILE is set, session keys are written to the file in NSS format. This is useful for debugging TLS connections (but breaks security, so don't use unless necessary).
  • Support proxies
  • Support client certs
  • Add connection/header timeouts, and read timeouts
  • And more!

Notes

This library only works with Go 1.15 and higher.

If you want relatively reliable code, use the latest tag, not the latest commit. Code in the latest master might be untested/buggy. The API might change between tags since it is still v0.

License

This library is under the ISC License, see the LICENSE file for details. Portions of this library's code are taken from Go, and are under a different license, which can be found in LICENSE-GO. Those files are marked accordingly in their comments.

Documentation

Overview

Package gemini provides an easy interface to create client and servers that speak the Gemini protocol.

At the moment, this library is client-side only, and support is not guaranteed. It is mostly a personal library.

It will automatically handle URLs that have IDNs in them, ie domains with Unicode. It will convert to punycode for DNS and for sending to the server, but accept certs with either punycode or Unicode as the hostname.

This also applies to hosts, for functions where a host can be passed specifically.

Index

Constants

View Source
const (
	URLMaxLength  = 1024
	MetaMaxLength = 1024
)
View Source
const (
	StatusInput          = 10
	StatusSensitiveInput = 11

	StatusSuccess = 20

	StatusRedirect          = 30
	StatusRedirectTemporary = 30
	StatusRedirectPermanent = 31

	StatusTemporaryFailure = 40
	StatusUnavailable      = 41
	StatusCGIError         = 42
	StatusProxyError       = 43
	StatusSlowDown         = 44

	StatusPermanentFailure    = 50
	StatusNotFound            = 51
	StatusGone                = 52
	StatusProxyRequestRefused = 53
	StatusBadRequest          = 59

	StatusClientCertificateRequired = 60
	StatusCertificateNotAuthorised  = 61
	StatusCertificateNotValid       = 62
)

Gemini status codes as defined in the Gemini spec Appendix 1.

Variables

View Source
var DefaultClient = &Client{ConnectTimeout: 15 * time.Second}

Functions

func CleanStatus

func CleanStatus(status int) int

CleanStatus returns the status code as is, unless it's invalid but still in range Then it returns the status code with the second digit zeroed. So 51 returns 51, but 22 returns 20.

This corresponds with the spec:

A client SHOULD deal with undefined status codes
between '10' and '69' per the default action of the initial digit.

func GetPunycodeURL

func GetPunycodeURL(u string) (string, error)

GetPunycodeURL takes a full URL that potentially has Unicode in the domain name, and returns a URL with the domain punycoded.

func IsStatusValid

func IsStatusValid(status int) bool

IsStatusValid checks whether an int status is covered by the spec. Note that:

A client SHOULD deal with undefined status codes
between '10' and '69' per the default action of the initial digit.

func QueryEscape

func QueryEscape(query string) string

QueryEscape provides URL query escaping in a way that follows the Gemini spec. It is the same as url.PathEscape, but it also replaces the +, because Gemini requires percent-escaping for queries.

func QueryUnescape

func QueryUnescape(query string) (string, error)

QueryUnescape is the same as url.PathUnescape

func SimplifyStatus

func SimplifyStatus(status int) int

SimplifyStatus simplify the response status by ommiting the detailed second digit of the status code.

func StatusInRange

func StatusInRange(status int) bool

StatusInRange returns true if the status has a valid first digit. This means it can be handled even if it's not defined by the spec, because it has a known category

func StatusText

func StatusText(code int) string

StatusText returns a text for the Gemini status code. It returns the empty string if the code is unknown.

Types

type Client

type Client struct {
	// NoTimeCheck allows connections with expired or future certs if set to true.
	NoTimeCheck bool

	// NoHostnameCheck allows connections when the cert doesn't match the
	// requested hostname or IP.
	NoHostnameCheck bool

	// Insecure disables all TLS-based checks, use with caution.
	// It overrides all the variables above.
	Insecure bool

	// AllowOutOfRangeStatuses means the client won't raise an error if a status
	// that is out of range is returned.
	// Use CleanStatus() to handle statuses that are in range but not specified in
	// the spec.
	AllowOutOfRangeStatuses bool

	// ConnectTimeout is equivalent to the Timeout field in net.Dialer.
	// It's the max amount of time allowed for the initial connection/handshake.
	// The timeout of the DefaultClient is 15 seconds.
	//
	// If ReadTimeout is not set, then this value is also used to time out on getting
	// the header after the connection is made.
	ConnectTimeout time.Duration

	// ReadTimeout is the max amount of time reading to a server can take.
	// This should not be set if you want to support streams.
	// It is equivalent to net.Conn.SetDeadline, see that func for more documentation.
	//
	// For example, if this is set to 30 seconds, then no more reading from the connection
	// can happen 30 seconds after the initial handshake.
	ReadTimeout time.Duration

	// Proxy is a function that returns an existing connection. The TLS client
	// will use this as the underlying transport, instead of making a direct TCP
	// connection.
	//
	// go-gemini requires setting a dialer on the underlying connection, to impose
	// a timeout on making the initial connection. This dialer is provided as an
	// argument to the proxy function.
	//
	// The other argument provided is the address being connected to. For example
	// "example.com:1965".
	//
	// Any errors returned will prevent a connection from occurring.
	//
	// This is not "gemini proxying", aka the proxying functionality built in to
	// the Gemini protocol. This is for proxying requests over TOR, or SOCKS5, etc.
	//
	//     func(dialer *net.Dialer, address string) (net.Conn, error)
	//
	Proxy ProxyFunc
}

func (*Client) Fetch

func (c *Client) Fetch(rawURL string) (*Response, error)

Fetch a resource from a Gemini server with the given URL. It assumes port 1965 if no port is specified.

func (*Client) FetchWithCert

func (c *Client) FetchWithCert(rawURL string, certPEM, keyPEM []byte) (*Response, error)

FetchWithCert fetches a resource from a Gemini server with the given URL. It allows you to provide the bytes of a PEM encoded block for a client certificate and its key. This allows you to make requests using client certs.

It assumes port 1965 if no port is specified.

func (*Client) FetchWithHost

func (c *Client) FetchWithHost(host, rawURL string) (*Response, error)

FetchWithHost fetches a resource from a Gemini server at the given host, with the given URL. This can be used for Gemini proxying, where the URL host and actual server don't match. It assumes the host is using port 1965 if no port number is provided.

func (*Client) FetchWithHostAndCert

func (c *Client) FetchWithHostAndCert(host, rawURL string, certPEM, keyPEM []byte) (*Response, error)

FetchWithHostAndCert combines FetchWithHost and FetchWithCert.

type Error

type Error struct {
	Err    error
	Status int
}

func (Error) Error

func (e Error) Error() string

func (Error) Unwrap

func (e Error) Unwrap() error

type ProxyFunc

type ProxyFunc func(dialer *net.Dialer, address string) (net.Conn, error)

ProxyFunc. See Client documentation

type Response

type Response struct {
	Status int
	Meta   string
	Body   io.ReadCloser
	Cert   *x509.Certificate
	// contains filtered or unexported fields
}

Response represents the response from a Gemini server.

func Fetch

func Fetch(url string) (*Response, error)

Fetch a resource from a Gemini server with the given URL. It assumes port 1965 if no port is specified.

func FetchWithCert

func FetchWithCert(url string, certPEM, keyPEM []byte) (*Response, error)

FetchWithCert fetches a resource from a Gemini server with the given URL. It allows you to provide the bytes of a PEM encoded block for a client certificate and its key. This allows you to make requests using client certs.

It assumes port 1965 if no port is specified.

func FetchWithHost

func FetchWithHost(host, url string) (*Response, error)

FetchWithHost fetches a resource from a Gemini server at the given host, with the given URL. This can be used for proxying, where the URL host and actual server don't match. It assumes the host is using port 1965 if no port number is provided.

func FetchWithHostAndCert

func FetchWithHostAndCert(host, url string, certPEM, keyPEM []byte) (*Response, error)

FetchWithHostAndCert combines FetchWithHost and FetchWithCert.

func (*Response) SetReadTimeout

func (r *Response) SetReadTimeout(d time.Duration) error

SetReadTimeout changes the read timeout after the connection has been made. You can set it to 0 or less to disable the timeout. Otherwise, the duration is relative to the time the function was called.

Jump to

Keyboard shortcuts

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