mediocrecaddyplugins

package module
v0.0.0-...-f5cea32 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2025 License: AGPL-3.0 Imports: 3 Imported by: 0

README

mediocre-caddy-plugins

Plugins to the Caddy webserver which I've developed for myself.

Build

A Caddy binary with these plugins included can be built using the xcaddy tool:

xcaddy build --with dev.mediocregopher.com/mediocre-caddy-plugins.git

If you want just a specific plugin you can choose it using its module path:

xcaddy build \
    --with dev.mediocregopher.com/mediocre-caddy-plugins.git/http/handlers/templates/functions

It's also possible to build Caddy manually using a custom main.go file, see the example from the caddy repo.

Plugins

The following plugins are implemented in this module.

http.handlers.gemtext

This HTTP handler will translate gemtext documents into HTML documents. It requires at least one argument, template, to which is passed an HTML template file that gemtext documents will be rendered into.

Only responses with a Content-Type of text/gemini will be modified by this module.

Example usage:

http://gemtext.localhost {
	root example/static
	gemtext {
		root example/tpl
		template render_gemtext.html
	}
	file_server
}
Parameters

template

Path to the template which will be used to render the HTML page, relative to the root.

The template will be rendered with these extra data fields:

  • .Title: The Title of the gemini document, determined based on the first primary header (single # prefix) found. This will be an empty string if no primary header is found.

  • .Body: A string containing all rendered HTML DOM elements.

heading_template

Path to a template which will be used for rendering headings. If not given then headings will be rendered with appropriate HTML header tags.

The template will be rendered with these extra data fields:

  • .Level: Which level of heading is being rendered, 1, 2, or 3.

  • .Text: The text of the heading.

link_template

Path to a template which will be used for rendering links. If not given then links will be rendered using an anchor tag wrapped in a paragraph tag.

The template will be rendered with these extra data fields:

  • .URL: The URL the link points to.
  • .Label: The label attached to the link. If the original link had no label then this will be equivalent to .URL.

root

The root path from which to load template files. Default is {http.vars.root} if set, or current working directory otherwise.

delimiters

The template action delimiters. Defaults to:

delimiters "{{" "}}"
http.handlers.gemlog_to_feed

This module will convert a gemtext response document into an RSS, Atom, or JSON feed, by first intepreting the gemtext document as a gemlog and making an appropriate conversion from there.

Example usage:

handle_path /gmisub.xml {
	# Rewrite the request path to point to the gemlog file
	rewrite /gmisub.gmi

	# Convert the response from file_server, which is the gemlog file itself,
	# into an ATOM feed.
	gemlog_to_feed {
		format atom
		author_name "Tester"
		author_email "[email protected]"
	}

	file_server
}
Parameters

format

Optional format of the feed to output. Can be one of rss, atom, or json, defaulting to atom.

The Content-Type of the response will be set accordingly.

author_name and author_email

Optional parameters which will be used to populate the top-level author fields in the output feed.

base_url

Optional URL in format [scheme://host[:port]]/path to use as the absolute URL all links in the feed will be relative to. If not given then it will be inferred from the request.

http.handlers.git_remote_repo

This module will serve a git repo using either the dumb or smart HTTP protocols, allowing clients to push to or pull from the repo.

This module does not deal with authentication or any other kind of access control, take care not to leave your private repos publicly exposed.

# git_remote_repo requires that the sub-directory in the URL path has already
# been stripped. handle_path takes care of this.
handle_path /repo.git/* {

	# Serve the git repository which can be found in the test-repo.git
	# sub-directory of the site root.
	git_remote_repo * "{http.vars.root}/test-repo.git"
}
http.handlers.proof_of_work

This module which will intercept all requests and check that they were made by a browser which has performed a proof-of-work (PoW) challenge in the recent past.

Any requests which lack a PoW solution will be redirected to a page where a challenge will be automatically solved. The challenge and solution will be stored in cookies, and then the browser will be redirected back to the page it was originally trying to get to.

The objective of this middleware is to allow normal users to continue using a website, while trying to prevent search engine crawlers, denial-of-service attacks, and AI scrapers from getting through.

Example Usage:

proof_of_work [matcher] {
	# all parameters are optional
	secret "some secret value"
	target 0x00FFFFFF
	challenge_timeout 12h
	challenge_seed_cookie "__pow_challenge_seed"
	challenge_solution_cookie "__pow_challenge_solution"
	template_path "{http.vars.root}/tpl.html"
}
Parameters

secret

Used to validate a PoW challenge seed. This string should never be shared with clients, but must be shared amongst all Caddy servers which are serving the same domain.

If not given then one will be generated on startup. Note that in this case restarting Caddy will result in all clients requiring a new PoW solution.

target

A uint32 indicating how difficult each challenge will be to solve. A lower Target value is more difficult than a higher one.

Defaults to 0x000FFFFF.

challenge_timeout

How long before Challenges are considered expired and cannot be solved. Any solutions are also expired, and browsers will be redirected back to the challenge page to solve a new challenge.

Defaults to 12h.

challenge_seed_cookie

The name of the cookie which should be used to store the challenge seed once a challenge has been solved.

Defaults to __pow_challenge_seed.

challenge_solution_cookie

The name of the cookie which should be used to store the challenge solution once a challenge has been solved.

Defaults to __pow_challenge_solution.

template

Path to HTML template to render in the browser when it is being challenged. If not given then a simple default is shown.

The template file should include the line <script>{{ template "pow.js" . }}</script> at the end of the body tag. This script will solve a challenge, set the solution to a cookie, and reload the page.

http.handlers.{request_timing_metric, response_size_metric}

Usage of these modules requires histograms to be defined under the mediocre_caddy_plugins.metrics global option set. Example:

// top-level options block, where directives like 'admin' and 'debug' go.
{
	mediocre_caddy_plugins {
		metrics {
			histogram custom_request_seconds {
				// All fields inside the block are optional
				help "Optional description of the metric"

				// Buckets defaults to this set of thresholds if not given
				buckets 0.005 0.01 0.025 0.05 0.1 0.25 0.5 1 2.5 5 10

				labels vhost path
			}

			histogram custom_response_bytes {
				buckets 256 1024 4096 16384 65536 262144 1048576 4194304
				labels vhost status
			}
		}
	}
}

These modules, which are used within an address block, will then passthrough all requests untouched, recording their timing/response size under the histogram metric referenced by name in the global options.

Example Usage:

mydomain.com {
	request_timing_metric "custom_request_seconds" {
		label vhost mydomain.com
		label path {http.request.uri.path}
		match status 200
	}

	response_size_metric "custom_response_bytes" {
		label vhost mydomain.com
		label status {http.response.status_code}
	}

	# ...
}
Parameters

label

Attach a label to the observation of each request. label can be specified multiple times to attach more than one label, and there must be the exact same set of labels within the metric as are defined in the globally defined histogram.

label values can contain placeholders, and the following placeholders are made available in this handler:

  • http.response.header.<header name>
  • http.response.status_code

match

A response matcher which can be used to only record metrics for requests whose response has particular characteristics.

http.handlers.templates.functions.gemtext_function

This extension to templates allows for rendering a gemtext string as a roughly equivalent set of HTML tags. It is similar to the markdown template function in its usage. It can be enabled by being included in the templates.extensions set.

templates {
    extensions {
        gemtext_function {
            # All parameters are optional
            gateway_url "https://some.gateway/x/"
        }
    }
}

See the template.localhost virtual host in ./example/Caddyfile, and the associated ./example/tpl/render_gemtext.html template file, for an example of how to use this directive.

Parameters

Optional parameters to the gemtext_function extension include:

gateway_url

If given then any gemini:// URLs encountered as links within the document will be appended to this URL, having their gemini:// scheme stripped off first.

e.g. if gateway_url is https://some.gateway/x/ then the following line:

=> gemini://geminiprotocol.net Check it out!

becomes

<a href="https://some.gateway/x/geminiprotocol.net">Check it out!</a>
Template function

Within a template being rendered the gemtext function will be available and can be passed any string. The function will return a struct with the following fields:

  • Body: The result of converting each line of the input string into an equivalent line of HTML. This will not include any wrapping HTML tags like <div> or <body>.

  • Title: A suggested title, based on the first # Header line found in the gemtext input.

Development

A nix-based development environment is provided with the correct versions of all development dependencies. It can be activated by doing:

nix-shell

The ./cmd/mediocre-caddy binary package can be used to run a Caddy instance with all plugins provided by this package pre-installed.

The Caddyfile ./example/Caddyfile can be used to spin up a Caddy instance with various virtual-hosts predefined with useful configurations for testing. See that file for a description of the available virtual hosts.

go run ./cmd/mediocre-caddy run --config ./example/Caddyfile

Documentation

Overview

Package mediocrecaddyplugins is an index package which automatically imports and registers all plugins defined in this module.

Directories

Path Synopsis
cmd
mediocre-caddy
Package main is the entry point of the Caddy application.
Package main is the entry point of the Caddy application.
Package global is used to set up a global mediocre_caddy_plugins App, which is primarily used for global options.
Package global is used to set up a global mediocre_caddy_plugins App, which is primarily used for global options.
http
handlers
Package handlers implements extra HTTP middlewares.
Package handlers implements extra HTTP middlewares.
handlers/templates/functions
Package functions makes available extra functions within templates being processed by the `http.handlers.templates` directive.
Package functions makes available extra functions within templates being processed by the `http.handlers.templates` directive.
internal
gemtext
Package gemtext implements shared logic related to gemtext files.
Package gemtext implements shared logic related to gemtext files.
pow
Package pow creates proof-of-work challenges and validates their solutions.
Package pow creates proof-of-work challenges and validates their solutions.
toolkit
Package toolkit contains useful, general-purpose utilities
Package toolkit contains useful, general-purpose utilities

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳