gus

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2023 License: Unlicense Imports: 7 Imported by: 0

README

Gus: The small web toolkit for Go

Gus is the toolkit for working with the small web in Go.

Think of it as a net/http for small web protocols. You still have to write your server, but you can focus on the logic you want to implement knowing the protocol is already dealt with. It's been said of gemini that you can write your server in a day. Now you can write it in well under an hour.

The "gus" package

Gus is carefully structured as composable building blocks. The top-level package defines the framework in which servers and clients can be built.

  • a request type
  • a response type
  • a "Server" interface type
  • a "Handler" abstraction
  • a "Middleware" abstraction
  • some useful Handler wrappers: a router, request filtering, falling through a list of handlers

Protocols

The packages gus/gemini, gus/gopher, and gus/finger provide concrete implementations of gus abstractions specific to those protocols.

  • I/O (parsing, formatting) request and responses
  • constructors for the various kinds of protocol responses
  • helpers for building a protocol-suitable TLS config
  • Client implementations
  • Servers which can run your Handlers.

The primary text formats for those protocols have higher-level support provided in sub-packages:

  • gus/gemini/gemtext supports parsing gemtext and getting direct programmatic access to its AST. Deeper sub-packages provide converters to other formats (markdown and HTML) with overridable templates.
  • gus/gopher/gophermap similarly parses the gophermap format and provides access to its AST.

Logging

Gus borrows the logging interface from go-kit.

=> The logger interface from go-kit/log.

The gus/logging package provides everything you need to get a good basic start to producing helpful logs.

  • A request-logging middleware with common diagnostics (time, duration, url, status codes, response body lengths)
  • A simple constructor of useful default loggers at various levels. They output colorful logfmt lines to stdout.

Routing

The router in the gus package supports slash-delimited path pattern strings. In the segments of these patterns:

  • A "/:wildcard/" segment matches anything in that position, and captures the value as a route parameter. Or if the paramter name is omitted like "/:/", it matches anything in a single segment without capturing a paramter.
  • A "/remainder" segment is only allowed at the end and matches the rest of the path, capturing it into the paramter name. Or again, omitting a parameter name like "/" simple matches any path suffix.
  • Any other segment in the pattern must match the corresponding segment of a request exactly.

Router also supports maintaining a list of middlewares at the router level, mounting sub-routers under a pattern, looking up the matching handler for any request, and of course acting as a Handler itself.

gus/contrib/*

This is where useful building blocks themselves start to come in. Sub-packages of contrib include Handler and Middleware implementations which accomplish the things your servers actually need to do.

The sub-packages include:

  • fs has handlers that make file servers possible: serve files, build directory listings, etc
  • cgi includes handlers which can execute CGI programs
  • sharedhost which provides means of handling /~username URLs
  • tlsauth contains middlewares and bool functions for authenticating against TLS client certificates
  • ...with more to come

Get it

Using gus in your project

To add it to your own go project:

$ go get tildegit.org/tjp/gus
Straight to the code please

=> The code is hosted here on tildegit.

=> The generated documentation is on the go package index.

Verify releases

Since v0.9.0, releases are signed with minisign. The signature file is included in the release downloads page, and the public key is RWSzQywJwHgjSMD0y0RXwXAGpapcMJplwbCVYQqabhAJ+NAnKAeh98Vb - this is also referenced on tjp's home page on gemini.

=> TJP's home page, which also mentions the public key used for signing gus releases.

Contribute

There's lots still to do, and contributions are very welcome!

=> submit an issue or pull request on the tildegit repository,

=> send me an email directly,

or poke me on IRC: I'm @tjp on irc.tilde.chat where you'll find me in #gemini


Step 2: draw the rest of the owl

;;;;;:::::::::::::::::::::::;;;;;;;,,,,,,,''''''''''',,,,,,,,,,,;;;;;;;;;;,,,,,,,,,,,,,,,,,,;;;;:::::::::::::;;
;;;;;;:::::::::::::::;;;;;;;;;;;,,,,,,,,'''''''''''''',,,,,,,,;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,,,;;;;::::::::::::;
;;;;;;;:::::::::::;;;;;;;;;;;,,,,,,,,,''''''''''''''',,,,,,,,;;;;;;;;::clooodddddddooooooodollc::;;:::::::::::;
;;;;;;;;;;;;;:::;;;;;;;;;;;;,,,,,,,,''''''''''''''''',,,,,,,,;;;;;:clodxkdodxdddooxxkxxxxkxxkxxxdlc::::::::::::
;;;;;;;;;;;;;;;;;;;;;;;;;;;,,,,,,,''''''''''''''''''',,,,,,,;;;;:lxkOkkkdolldl:c::loooolloclccolddolc:::::::::;
;;;;;;;;;;;;;;;;;;;;;;;;;;,,,,,,,''''''''''''''''''''',,,,,;;::oxOOOOkxxdoodkxlcc;;clcc:lccllddclloddol::::::;;
;;;;;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,'''''''''''''''''''',,,,;;cdxxkkxdollllloodoodoc:::;:lddxxxOkdlldxkdolc;::;;;
;;;;;;,,,;;;;;;;;;;;;;;;;,,,,,,,,,,'''''''''''''''''''',,,;cdkkkxdollc::;,''',;lodd:;;cxkxdolllolc::ldool:;;;;;
,,,,,,,,,,;;;;;;;;;;;;;;;,,,,,,,,,,,,'''''''''''''''''',,,cdkkxdlc:cc:;........':odo::lolc;'...';:::::lool:;;;;
,,,,,,,,,,,,;;;;;;;;;;;;;,,,,,,,,,,,,,'''''''''''''''',,,:dkxxdolcccc::'':'.....,loollol,.........,;;::cll:;;;;
,,,,,,,,,,,,,,,,,;;;;;;;;;,,,,,,,,,,,,,,'''''''''',,,,,,;oxxxdllccccloo;'c:'';:,;codxdlc,'.   ,,.,::::::lc:;;;;
,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;,,,,,,,,,,,,,,,,,,,,,,,,;lddddlc:;;:cldxdcclc::::cclddooc,';,',:,,clc::;:lc;;;;;
,,,,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;,,,,,,,,,,,,,,,,,,,,,:odddolc:;;::cloxxddocclllc::::ll:;;;:c::odoc;;;:lc;;;;;
;,,,,,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;,,,,,,,,,,,cdolloool:;;::cloddoooodoc;'''.:lllollddddl::;;;;::;;;;;
;;;,,,,,,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;;;;;,:odooxxooolc:::codxdlcllll:'....;ccccodddlc:;,,;;:c:,,,,,
;;;;,,,,,,,,,,,,,,,,,,,,,,,,;;;;;;;;;;::::::;;;;;;;;;:oxkO0KX0Oxolccccllodddddolc:'..;clcccclddl;,',,',::;,,,,,
;;;;;,,,,,,,,,,,,,,,,,,,,,,,;;;;;;;;;::::::::::::;:clodddooxOkxdol:coollodxkdl:,,'..';:looddool:;,'.';;::,,,,,;
;;;;;,,,,,,,,,,,,,,,,,,,,,,,;;;;;;;;::::::::::::ccloollloollc::::;;:lccodxkxlco:.......',cdxxdl;,,''';::;;;;;;;
;;;;;;,,,,,,,,,,,,,,,,,,,,,,,,;;;;;;;::::::::ccllccoolcclc:::::clc;;:;,;;cc,,cxd;,'......,:oxdol:;,;loc;;;;;;;;
;;;;;;,,,,,,,,,,,,,,,,,,,,,,,,,;;;;;;:::::cclllccccc::;;;;:ooc:oOxloxl'....,collddlc;'..';:lddoxdlldxdc;;;;::::
;;;;;;,,,,,,,,,,,,,,,,,,,,,,,,,,;;;;;:odooolcccccc::;:odlcoxdc;cldOKx;''''';:;,;loc;,'',,,,:clodkkkOkl:;:::::::
;;;;;;,,,,,,,,,,,,,,,,,,,,,,,,,,,;;:lxOxolllllccllc::x0xc;;c:''':kN0c,,;;;;;;,,',,,,''''''..,::lododdc:::::cccc
;;;;;,,,,,,,,,,,,,,,,,,,,,,,,,,,,;lxdolc:codoolcllc;:cc:,''''.'';lxo::::;;;;;;,''''.........:l;;::;:ol:::cccccc
;;;;;,,,,,,,,,,,,,,,,,,''',,,,,,:dxc'':loOKkdoccll:,,;;;,',,;:::;;;;::;;;;;;;;,,,...........,;,,',,;c::cccccccc
,,,,,,,,,,,,,,,,,,,,,,,'''''';:lol,':dxx0Xkolc::lc;;;;::;,;;:::;;;::::;;;;,,,',,,...........,;''''',:::ccccllll
,,,,,,,,,,,,,,,,,,,,,,,'''';ldl,..'cOKkdkdccccc:::::::::;;;:::;;:c:;;;,,,,'''''','........,;;'.',;;;:::ccllllll
,,,,,,,,,,,,,,,,,,,,,,,',;clc,.. .ckOkdlllccccc:c::::::::::;;;:::;;,,'''''...';,''.....';cl:'',;:ll:::ccccllccc
,,,,,,,,,,,,,,,,,,,,,,,;cl;......:loollcccccc::::::::c:;;,;;;;;;;,,,:l:'......'......,:llc;'',:codl::cccccccccc
,,,,,,,,,,,,,,,,,,,,;ccl:..  .':ldollc::::::::;;;;;;,;:,',;;;;;;;,',ox:..........',::::;,,,'';cllcccccccccccccc
',,,,,,,,,,,,,,,,,:ll:;,.  .';cclllll:::::;;,,,,,,'..''',,,,;::;,'..........'..',;c:'.',;,''':ccccccccccccccccc
',,,,,,,,,,,,,;;;::'..   .,:cccc::cc:::;;,''',,'....,cc,'',;,'............'',;c:,,''',:c,,;,;ccccccclllllllcccc
',,,,,,,,,,;;;;,..    ..,:::::ccclolcc;;,,'''.',,''',::;,'..........',,;;:::::;'.,,,,cc,,;;:cccllllllllllllllll
'',,,,,,,,;;'..     .';::::clllolcc:;,;;;;,;;:;,'','................,:ccc::,''',;;,;::;,;::ccclllllllllllllllll
''',,,,,;:,..      .,;;;:clolc::;;;cc:;;;,;cc;,'..''..............',;;;;;;,',;::;;;::;;::::ccclllllllllllllllll
'''',,,,;'.      ..',;::cc:;;,;;:ccc:;,,:lol;'''........''''..'',,;:ccc;,',:lc;,,,;;;;:::::ccclllllllllllllllll
'''''',;,..   ....,;:c::;:::::;:cc:,'''',,,'',,'....'';ccc::::::;;;:::,'':cc;,,,',;;;;;::::ccclllllllllllllllll
''''''':c,....',,:llllllc::;,:lo:,'',;;,,,,;;,,,'',;;cdxdllclllccccl:;,,::;,'''',,,,;;;;::::cccclllllcccccccccc
'''''',;lc'..,:ccllllcc:;,,;;clc::::cccccccc::::::clldxdoolloolcclc:;,,;,,;,,,,,,,,,,;;;;;:::cccccccccccccccccc
''''';lolc:ccllllc::::;;:cloollllllccclllooollooooooodolcclloc:;,,,;;,',,;,,,,,,,,,,,;;;;;;;::::ccccccccccc::::
'''';odl::lolc;,'...,codxxxxxddolcccllloooddddxxxxxdddlcccllc;,,;:::;,,;,,,,,,,,,,,,,,,,;;;;;;::::::::::::::::;
''',colc::;,......,coxxxdxxxol:;;;;:cloodddddddxxxxxddoooddlcccll:loo:;::,,,,,,,,,,,,,,,,,,,,;;;;;;:::::::;;;;;
'',co:,,,'...''..,:cccc:;::;,,,,,,;;:lodxddddooddddoooolcoxxdolc;,:ldxodoc:c:,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;,
''cOxcc;,,,;,'.''',,'',,,,,,,,,,,,,,;:clooddollooolllll;,cxkxol:,:,';llllodddo:,,,,,,,,,,,,,,,,,,,;;;;,,,,,,,,,
'';xkxoc,,,'..''',,,,,,,,,,,,,,,,,,,,,;;;:ccc::ccc:;::,';;;:cloodl;;,,:::lodOOl,',,,,,,,,,,,,,,,,,,,,,,,,,,,,,'
''',:c:,'';:;;;,,,,,,,,,,,,,,,,,,,,,,,,,,,;;,,;;;;,;;;'';;',oxddxocc:;clloxxk00kddc;,,,,,,,,,,,,,,,,,,,,,''''''
,''''''''';::,''''',,,,,,,,,,,,,,,,,,,,,,,;::cclccccc:,,,,.'loc;,:lllodoodkOO0KKKKOl;,;,,,,,,,,,,,,,,,,,,''''''
'''''''''''''''''''',,,,,,,,,,,,,,,,,,,,;clllcc::;,'...'...,lc:'.,c;:oook00OddO00KKd,,;;,;;;;,,,,,,,,,,,,,,,,''
'''''''''''''''''''',,,,,,,,,,,,,,,,;;::c:::;;,,''.....'''.:dl:'.,ll;',oKXXd;;:lod00dc::;;,;,,,,,,,,,,,,,,,,,,,
'''''''''''''''''',,,,,,,,;;;;,,,,;::ccccc::;;;,,,'..'''''';dc....:xxl;cxkkl:;;;::lddl:coc;,,,,,,,,,,,,,,,,,,,,
'''''''''''''''',,,,,;;;;;;;;;;;:clc:ccc::;;;;;,,'',,,,,,,,;lc'''',oOOxo;';cllccc:;:l:'':loc;,,,,,,,,,,,,,,,,,,
,''''''''''',,,,,,;;;;;;;::;;;::llc::::::;;:;;;:;;;;;;;;;;;;:cc;,,':k000x:;lddddoolodd:.'ldxo:,,,,,,,,,,,,,,'''
,'''''''''',,,,,;;;:::::::::cllllcccc::c:::::::cc::;;;;;;;;;;:cc:;,,lOKKK0dodxxxdollccl:,,codl;''''',,,,,''',''
,,''''''',,,,;;;;:::::::::cloooolcccc:::;;:::cc::;;,,;;;:;;;;;;:cc:,,oKKKKOddxxo:;:c::;:;',;:cc;''''''''''',,,,

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RouteParams added in v1.0.0

func RouteParams(ctx context.Context) map[string]string

RouteParams gathers captured path parameters from the request context.

If the context doesn't contain a parameter map, it returns nil. If Router was used but no parameters were captured in the pattern, it returns a non-nil empty map.

Types

type Handler

type Handler interface {
	Handle(context.Context, *Request) *Response
}

Handler is a type which can turn a request into a response.

Handle may return a nil response, in which case the Server is expected to build the protocol-appropriate "Not Found" response.

func FallthroughHandler

func FallthroughHandler(handlers ...Handler) Handler

FallthroughHandler builds a handler which tries multiple child handlers.

The returned handler will invoke each of the passed-in handlers in order, stopping when it receives a non-nil response.

func HandlerFunc added in v1.0.0

func HandlerFunc(f func(context.Context, *Request) *Response) Handler

HandlerFunc is a wrapper to allow using a function as a Handler.

type Middleware

type Middleware func(Handler) Handler

Middleware is a handler decorator.

It returns a handler which may call the passed-in handler or not, or may transform the request or response in some way.

func Filter

func Filter(
	condition func(context.Context, *Request) bool,
	failure Handler,
) Middleware

Filter builds a middleware which only calls the wrapped Handler under a condition.

When the condition function returns false it instead invokes the test-failure handler. The failure handler may also be nil, in which case the final handler will return a nil response whenever the condition fails.

type Request

type Request struct {
	// URL is the specific URL being fetched by the request.
	*url.URL

	// Server is the server which received the request.
	//
	// This is only populated in servers.
	// It is unused on the client end.
	Server Server

	// RemoteAddr is the address of the other side of the connection.
	//
	// This will be the server address for clients, or the connecting
	// client's address in servers.
	//
	// Be aware though that proxies (and reverse proxies) can confuse this.
	RemoteAddr net.Addr

	// TLSState contains information about the TLS encryption over the connection.
	//
	// This includes peer certificates and version information.
	TLSState *tls.ConnectionState
}

Request represents a request over any small web protocol.

Because protocols have so many differences, this type represents a greatest common denominator of request/response-oriented protocols.

func (Request) UnescapedQuery

func (req Request) UnescapedQuery() string

UnescapedQuery performs %XX unescaping on the URL query segment.

Like URL.Query(), it silently drops malformed %-encoded sequences.

type Response

type Response struct {
	// Status is the status code of the response.
	Status Status

	// Meta contains status-specific additional information.
	Meta any

	// Body is the response body, if any.
	Body io.Reader
}

Response contains the data in a response over the small web.

Because protocols have so many differences, this type represents a greatest common denominator of request/response-oriented protocols.

func (*Response) Close

func (response *Response) Close() error

type ResponseReader added in v0.9.0

type ResponseReader interface {
	io.Reader
	io.WriterTo
	io.Closer
}

ResponseReader is an object which can serialize a response to a protocol.

type Router added in v1.0.0

type Router struct {
	// contains filtered or unexported fields
}

Router stores a mapping of request path patterns to handlers.

Pattern may begin with "/" and then contain slash-delimited segments.

  • Segments beginning with colon (:) are wildcards and will match any path segment at that location. It may optionally have a word after the colon, which will be the parameter name the path segment is captured into.
  • Segments beginning with asterisk (*) are remainder wildcards. This must come last and will capture any remainder of the path. It may have a name after the asterisk which will be the parameter name.
  • Any other segment in the pattern must match a path segment exactly.

These patterns do not match any path which shares a prefix, rather then full path must match a pattern. If you want to only match a prefix of the path you can end the pattern with a *remainder segment.

The zero value is a usable Router which will fail to match any requst path.

func (Router) Handler added in v1.0.0

func (r Router) Handler(ctx context.Context, request *Request) *Response

Handler matches against the request path and dipatches to a route handler.

If no route matches, it returns a nil response. Captured path parameters will be stored in the context passed into the handler and can be retrieved with RouteParams().

func (Router) Match added in v1.0.0

func (r Router) Match(request *Request) (Handler, map[string]string)

Match returns the matched handler and captured path parameters, or (nil, nil).

The returned handlers will be wrapped with any middleware attached to the router.

func (*Router) Mount added in v1.0.0

func (r *Router) Mount(prefix string, subrouter *Router)

Mount attaches a sub-router to handle path suffixes after an initial prefix pattern.

The prefix pattern may include segment :wildcards, but no *remainder segment. The mounted sub-router should have patterns which only include the portion of the path after whatever was matched by the prefix pattern.

func (*Router) Route added in v1.0.0

func (r *Router) Route(pattern string, handler Handler)

Route adds a handler to the router under a path pattern.

func (*Router) Use added in v1.0.0

func (r *Router) Use(mw Middleware)

Use attaches a middleware to the router.

Any routes set on the router will have their handlers decorated by the attached middlewares in reverse order (the first middleware attached will be the outer-most: first to see requests and the last to see responses).

Use will panic if Route or Mount have already been called on the router - middlewares must be set before any routes.

type Server

type Server interface {
	// Serve blocks listening for connections on an interface.
	//
	// It will only return after Close() has been called.
	Serve() error

	// Close initiates a graceful shutdown of the server.
	//
	// It blocks until all resources have been cleaned up and all
	// outstanding requests have been handled and responses sent.
	Close()

	// Closed indicates whether Close has been called.
	//
	// It may be true even if the graceful shutdown procedure
	// hasn't yet completed.
	Closed() bool

	// Protocol returns the protocol being served by the server.
	Protocol() string

	// Network returns the network type on which the server is running.
	Network() string

	// Address returns the address on which the server is listening.
	Address() string

	// Hostname returns just the hostname portion of the listen address.
	Hostname() string

	// Port returns the port on which the server is listening.
	//
	// It will return the empty string if the network type does not
	// have ports (unix sockets, for example).
	Port() string

	// LogError sends a log message to the server's error log.
	LogError(keyvals ...any) error
}

Server is a type which can serve a protocol.

type Status

type Status int

Status is the integer status code of a response.

Directories

Path Synopsis
Contrib contains sub-packages with specific functionality for small web servers.
Contrib contains sub-packages with specific functionality for small web servers.
cgi
fs
examples
cgi
The gemini package contains everything needed for building clients and servers on the gemini protocol.
The gemini package contains everything needed for building clients and servers on the gemini protocol.
gemtext
The gemtext package contains a gemtext AST and parser.
The gemtext package contains a gemtext AST and parser.

Jump to

Keyboard shortcuts

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