💾 Archived View for godocs.io › github.com › pitr › gig captured on 2024-06-16 at 17:10:29. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-05-26)
-=-=-=-=-=-=-
import "github.com/pitr/gig"
Package gig implements high performance, minimalist Go framework for Gemini protocol.
Example:
package main import ( "github.com/pitr/gig" ) func main() { // Gig instance g := gig.Default() // Routes g.Handle("/user/:name", func(c gig.Context) error { return c.Gemini(gig.StatusSuccess, "# Hello, %s!", c.Param("name")) }) // Start server g.Run("my.crt", "my.key") }
const ( MIMETextGemini = "text/gemini" MIMETextGeminiCharsetUTF8 = "text/gemini; charset=UTF-8" MIMETextPlain = "text/plain" MIMETextPlainCharsetUTF8 = "text/plain; charset=UTF-8" )
MIME types.
const ( // Version of Gig. Version = "0.9.8" )
var ( // DefaultWriter is the default io.Writer used by gig for debug output and // middleware output like Logger() or Recovery(). // Note that both Logger and Recovery provides custom ways to configure their // output io.Writer. // To support coloring in Windows use: // import "github.com/mattn/go-colorable" // gig.DefaultWriter = colorable.NewColorableStdout() DefaultWriter io.Writer = os.Stdout // Debug enables gig to print its internal debug messages. Debug = true )
var ( ErrTemporaryFailure = NewError(StatusTemporaryFailure, "Temporary Failure") ErrServerUnavailable = NewError(StatusServerUnavailable, "Server Unavailable") ErrCGIError = NewError(StatusCGIError, "CGI Error") ErrProxyError = NewError(StatusProxyError, "Proxy Error") ErrSlowDown = NewError(StatusSlowDown, "Slow Down") ErrPermanentFailure = NewError(StatusPermanentFailure, "Permanent Failure") ErrNotFound = NewError(StatusNotFound, "Not Found") ErrGone = NewError(StatusGone, "Gone") ErrProxyRequestRefused = NewError(StatusProxyRequestRefused, "Proxy Request Refused") ErrBadRequest = NewError(StatusBadRequest, "Bad Request") ErrClientCertificateRequired = NewError(StatusClientCertificateRequired, "Client Certificate Required") ErrCertificateNotAuthorised = NewError(StatusCertificateNotAuthorised, "Certificate Not Authorised") ErrCertificateNotValid = NewError(StatusCertificateNotValid, "Certificate Not Valid") ErrRendererNotRegistered = errors.New("renderer not registered") ErrInvalidCertOrKeyType = errors.New("invalid cert or key type, must be string or []byte") ErrServerClosed = errors.New("gemini: Server closed") )
Errors that can be inherited from using NewErrorFrom.
var ( // DefaultCertAuthConfig is the default CertAuth middleware config. DefaultCertAuthConfig = CertAuthConfig{ Skipper: DefaultSkipper, Validator: ValidateHasCertificate, } )
var ( // DefaultLoggerConfig is the default Logger middleware config. DefaultLoggerConfig = LoggerConfig{ Skipper: DefaultSkipper, Format: "time=\"${time_rfc3339}\" path=${path} status=${status} duration=${latency} ${error}\n", CustomTimeFormat: "2006-01-02 15:04:05.00000", } )
var ( // DefaultRecoverConfig is the default Recover middleware config. DefaultRecoverConfig = RecoverConfig{ Skipper: DefaultSkipper, StackSize: 4 << 10, DisableStackAll: false, DisablePrintStack: false, } )
var ( NotFoundHandler = func(c Context) error { return ErrNotFound } )
Error handlers.
func DefaultGeminiErrorHandler(err error, c Context)
DefaultGeminiErrorHandler is the default HTTP error handler. It sends a JSON response with status code.
func DefaultSkipper(Context) bool
DefaultSkipper returns false which processes the middleware.
type CertAuthConfig struct { // Skipper defines a function to skip middleware. Skipper Skipper // Validator is a function to validate client certificate. // Required. Validator CertAuthValidator }
CertAuthConfig defines the config for CertAuth middleware.
type CertAuthValidator func(*x509.Certificate, Context) *GeminiError
CertAuthValidator defines a function to validate CertAuth credentials.
type Context interface { // Response returns `*Response`. Response() *Response // IP returns the client's network address. IP() string // Certificate returns client's leaf certificate or nil if none provided Certificate() *x509.Certificate // CertHash returns a hash of client's leaf certificate or empty string is none CertHash() string // URL returns the URL for the context. URL() *url.URL // Path returns the registered path for the handler. Path() string // QueryString returns unescaped URL query string or error. Use // Context#URL().RawQuery to get raw query string QueryString() (string, error) // RequestURI is the unmodified URL string as sent by the client // to a server. Usually the URL() or Path() should be used instead. RequestURI() string // Param returns path parameter by name. Param(name string) string // Get retrieves data from the context. Get(key string) interface{} // Set saves data in the context. Set(key string, val interface{}) // Render renders a template with data and sends a text/gemini response with status // code Success. Renderer must be registered using `Gig.Renderer`. Render(name string, data interface{}) error // Gemini sends a text/gemini response with status code Success. Gemini(text string, args ...interface{}) error // GeminiBlob sends a text/gemini blob response with status code Success. GeminiBlob(b []byte) error // Text sends a text/plain response with status code Success. Text(format string, values ...interface{}) error // Blob sends a blob response with status code Success and content type. Blob(contentType string, b []byte) error // Stream sends a streaming response with status code Success and content type. Stream(contentType string, r io.Reader) error // File sends a response with the content of the file. File(file string) error // NoContent sends a response with no body, and a status code and meta field. // Use for any non-2x status codes NoContent(code Status, meta string, values ...interface{}) error // Error invokes the registered error handler. Generally used by middleware. Error(err error) // Handler returns the matched handler by router. Handler() HandlerFunc // Gig returns the `Gig` instance. Gig() *Gig }
Context represents the context of the current request. It holds connection reference, path, path parameters, data and registered handler. DO NOT retain Context instance, as it will be reused by other connections.
type FakeAddr struct{}
FakeAddr ia a fake net.Addr implementation.
func (a *FakeAddr) Network() string
Network returns dummy data.
func (a *FakeAddr) String() string
String returns dummy data.
type FakeConn struct { FailAfter int Written string }
FakeConn ia a fake net.Conn that can record what is written and can fail after FailAfter bytes were written.
func (c *FakeConn) Close() error
Close always returns nil.
func (c *FakeConn) LocalAddr() net.Addr
LocalAddr returns fake address.
func (c *FakeConn) Read(b []byte) (n int, err error)
Read always returns success.
func (c *FakeConn) RemoteAddr() net.Addr
RemoteAddr returns fake address.
func (c *FakeConn) SetDeadline(t time.Time) error
SetDeadline always returns nil.
func (c *FakeConn) SetReadDeadline(t time.Time) error
SetReadDeadline always returns nil.
func (c *FakeConn) SetWriteDeadline(t time.Time) error
SetWriteDeadline always returns nil.
func (c *FakeConn) Write(b []byte) (n int, err error)
Write records bytes written and fails after FailAfter bytes.
type GeminiError struct { Code Status Message string }
GeminiError represents an error that occurred while handling a request.
func NewError(code Status, message string) *GeminiError
NewError creates a new GeminiError instance.
func NewErrorFrom(err *GeminiError, message string) *GeminiError
NewErrorFrom creates a new GeminiError instance using Code from existing GeminiError.
func ValidateHasCertificate(cert *x509.Certificate, c Context) *GeminiError
ValidateHasCertificate returns ErrClientCertificateRequired if no certificate is sent. It also stores subject name in context under "subject".
func (ge *GeminiError) Error() string
Error makes it compatible with `error` interface.
type GeminiErrorHandler func(error, Context)
GeminiErrorHandler is a centralized error handler.
type Gig struct { // HideBanner disables banner on startup. HideBanner bool // HidePort disables startup message. HidePort bool // GeminiErrorHandler allows setting custom error handler GeminiErrorHandler GeminiErrorHandler // Renderer must be set for Context#Render to work Renderer Renderer // ReadTimeout set max read timeout on socket. // Default is none. ReadTimeout time.Duration // WriteTimeout set max write timeout on socket. // Default is none. WriteTimeout time.Duration // TLSConfig is passed to tls.NewListener and needs to be modified // before Run is called. TLSConfig *tls.Config // contains filtered or unexported fields }
Gig is the top-level framework instance.
func Default() *Gig
Default returns a Gig instance with Logger and Recover middleware enabled.
func New() *Gig
New creates an instance of Gig.
func (g *Gig) Close() error
Close immediately stops the server. It internally calls `net.Listener#Close()`.
func (g *Gig) File(path, file string, m ...MiddlewareFunc) *Route
File registers a new route with path to serve a static file with optional route-level middleware.
func (g *Gig) Group(prefix string, m ...MiddlewareFunc) (gg *Group)
Group creates a new router group with prefix and optional group-level middleware.
func (g *Gig) Handle(path string, h HandlerFunc, m ...MiddlewareFunc) *Route
Handle registers a new route for a path with matching handler in the router with optional route-level middleware.
func (g *Gig) NewFakeContext(uri string, tlsState *tls.ConnectionState) (Context, *FakeConn)
NewFakeContext returns Context that writes to FakeConn.
func (g *Gig) PassAuthLoginHandle(path string, fn PassAuthLogin)
PassAuthLoginHandle sets up handlers to check username/password using PassAuthLogin.
func (g *Gig) Pre(middleware ...MiddlewareFunc)
Pre adds middleware to the chain which is run before router.
func (g *Gig) Reverse(name string, params ...interface{}) string
Reverse generates an URL from route name and provided parameters.
func (g *Gig) Routes() []*Route
Routes returns the registered routes.
func (g *Gig) Run(args ...interface{}) (err error)
Run starts a Gemini server. If `certFile` or `keyFile` is `string` the values are treated as file paths. If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is.
func (g *Gig) ServeGemini(c Context)
ServeGemini serves Gemini request.
func (g *Gig) Static(prefix, root string) *Route
Static registers a new route with path prefix to serve static files from the provided root directory.
func (g *Gig) URL(handler HandlerFunc, params ...interface{}) string
URL generates a URL from handler.
func (g *Gig) Use(middleware ...MiddlewareFunc)
Use adds middleware to the chain which is run after router.
type Group struct { // contains filtered or unexported fields }
Group is a set of sub-routes for a specified route. It can be used for inner routes that share a common middleware or functionality that should be separate from the parent gig instance while still inheriting from it.
func (g *Group) File(path, file string)
File implements `Gig#File()` for sub-routes within the Group.
func (g *Group) Group(prefix string, middleware ...MiddlewareFunc) *Group
Group creates a new sub-group with prefix and optional sub-group-level middleware.
func (g *Group) Handle(path string, h HandlerFunc, m ...MiddlewareFunc) *Route
Handle implements `Gig#Handle()` for sub-routes within the Group.
func (g *Group) Static(prefix, root string)
Static implements `Gig#Static()` for sub-routes within the Group.
func (g *Group) Use(middleware ...MiddlewareFunc)
Use implements `Gig#Use()` for sub-routes within the Group.
type HandlerFunc func(Context) error
HandlerFunc defines a function to serve requests.
type LoggerConfig struct { // Skipper defines a function to skip middleware. Skipper Skipper // Tags to construct the logger format. // // - time_unix // - time_unix_nano // - time_rfc3339 // - time_rfc3339_nano // - time_custom // - remote_ip // - uri // - host // - path // - status // - error // - latency (In nanoseconds) // - latency_human (Human readable) // - bytes_in (Bytes received) // - bytes_out (Bytes sent) // - meta // - query // // Example "${remote_ip} ${status}" // // Optional. Default value DefaultLoggerConfig.Format. Format string // Optional. Default value DefaultLoggerConfig.CustomTimeFormat. CustomTimeFormat string // contains filtered or unexported fields }
LoggerConfig defines the config for Logger middleware.
type MiddlewareFunc func(HandlerFunc) HandlerFunc
MiddlewareFunc defines a function to process middleware.
func CertAuth(fn CertAuthValidator) MiddlewareFunc
CertAuth returns an CertAuth middleware.
For valid credentials it calls the next handler.
func CertAuthWithConfig(config CertAuthConfig) MiddlewareFunc
CertAuthWithConfig returns an CertAuth middleware with config. See `CertAuth()`.
func Logger() MiddlewareFunc
Logger returns a middleware that logs Gemini requests.
func LoggerWithConfig(config LoggerConfig) MiddlewareFunc
LoggerWithConfig returns a Logger middleware with config. See: `Logger()`.
func PassAuth(check PassAuthCertCheck) MiddlewareFunc
PassAuth is a middleware that implements username/password authentication by first requiring a certificate, checking username/password using PassAuthValidator, and then pinning certificate to it.
For valid credentials it calls the next handler.
func Recover() MiddlewareFunc
Recover returns a middleware which recovers from panics anywhere in the chain and handles the control to the centralized GeminiErrorHandler.
func RecoverWithConfig(config RecoverConfig) MiddlewareFunc
RecoverWithConfig returns a Recover middleware with config. See: `Recover()`.
type PassAuthCertCheck func(string, Context) (string, error)
PassAuthCertCheck defines a function to validate certificate fingerprint. Must return path on unsuccessful login.
type PassAuthLogin func(username, password, sig string, c Context) (string, error)
PassAuthLogin defines a function to login user. It may pin certificate to user if login is successful. Must return path to redirect to after login.
type RecoverConfig struct { // Skipper defines a function to skip middleware. Skipper Skipper // Size of the stack to be printed. // Optional. Default value 4KB. StackSize int // DisableStackAll disables formatting stack traces of all other goroutines // into buffer after the trace for the current goroutine. // Optional. Default value false. DisableStackAll bool // DisablePrintStack disables printing stack trace. // Optional. Default value as false. DisablePrintStack bool }
RecoverConfig defines the config for Recover middleware.
type Renderer interface { Render(io.Writer, string, interface{}, Context) error }
Renderer is the interface that wraps the Render function.
type Response struct { Writer io.Writer Status Status Meta string Size int64 Committed bool // contains filtered or unexported fields }
Response wraps net.Conn, to be used by a context to construct a response.
func NewResponse(w io.Writer) (r *Response)
NewResponse creates a new instance of Response. Typically used for tests.
func (r *Response) Write(b []byte) (int, error)
Write writes the data to the connection as part of a reply.
func (r *Response) WriteHeader(code Status, meta string) error
WriteHeader sends a Gemini response header with status code. If WriteHeader is not called explicitly, the first call to Write will trigger an implicit WriteHeader(StatusSuccess, "text/gemini"). Thus explicit calls to WriteHeader are mainly used to send error codes.
type Route struct { Path string Name string }
Route contains a handler and information for matching against requests.
type Skipper func(Context) bool
Skipper defines a function to skip middleware. Returning true skips processing the middleware.
type Status int
Status is a Gemini status code type.
const ( StatusInput Status = 10 StatusSensitiveInput Status = 11 StatusSuccess Status = 20 StatusRedirectTemporary Status = 30 StatusRedirectPermanent Status = 31 StatusTemporaryFailure Status = 40 StatusServerUnavailable Status = 41 StatusCGIError Status = 42 StatusProxyError Status = 43 StatusSlowDown Status = 44 StatusPermanentFailure Status = 50 StatusNotFound Status = 51 StatusGone Status = 52 StatusProxyRequestRefused Status = 53 StatusBadRequest Status = 59 StatusClientCertificateRequired Status = 60 StatusCertificateNotAuthorised Status = 61 StatusCertificateNotValid Status = 62 )
Gemini status codes as documented by specification. See: https://gemini.circumlunar.space/docs/spec-spec.txt