diecast

package module
v1.9.13 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2018 License: LGPL-2.1 Imports: 72 Imported by: 0

README

diecast GoDoc

A standalone web server that consumes REST services, passes the response into templates, and serves the results.

Overview

Diecast is a utility and importable Golang package that allows you to dynamically render a directory tree of template files into HTML,CSS or anything else text-based. Data can be retrieved from third-party API sources and on-the-fly included during the template rendering process. This allows you to create entire websites that consume external data sources and present a complete UI for them without the need to write intermediary logic.

Goals

The primary goal of this project is to make the process of building data-driven web applications easier by reducing cognitive load on the developer. Rather than tackling the problem using conventional web frameworks, Diecast instead tries to operate more along the lines of a static site generator (like Jekyll or Hugo), except that it operates as a long-running process that continuously serves and renders templates in real time. The benefit here (I hope) is that, for relatively small sites that don't require extensive URL routing logic beyond what can be achieved by a filesystem-oriented approach, you gain a declarative interface to consuming data from APIs, using the templates to guide that data along the path to becoming HTML, CSS, Javascript, or any other text-oriented format.

Example

The following shows an example that illustrates basic usage of diecast for a simple "Hello World" site with no external content. You can try this out by installing Diecast (go get github.com/ghetzel/diecast), changing to the examples/hello-world directory, and running diecast. The site is available at [http://localhost:28419].

Directory tree:

$ cd ./examples/hello-world
$ tree
.
├── functions.html
├── home.html
├── image.gif
├── index.html
├── main.css
└── thing
    └── index.html

1 directory, 6 files

Navigation

By visiting [http://localhost:28419], you will be presented with a web page representing the contents of the index.html file. Because there is a layout present (in _layouts/default.html), the index page will inserted into that layout before being returned. Using layouts and includes along with templates allows for extensive code reuse throughout your site.

The name of the template file becomes the URL path used to access that file. For example, the functions.html file is accessible by going to [http://localhost:28419/functions].

Bindings

Bindings are a mechanism that tell Diecast which (if any) remote API resources should be loaded before rendering a template. In the example above, there are two bindings configured: current_user and objects. The current_user binding is flagged as optional, meaning that if there is an error in the request (connection error, SSL error, non-2xx HTTP status), the value will return nil instead of causing a fatal error. The objects binding is required, so any errors in retrieval will cause a fatal error in the page.

Bindings, in concert with Templates, are how you consume third-party remote APIs and turn those responses into usable web applications.

Templating

By default, HTML files served through diecast will treated as templates and rendered, with all other files being served as-is (static resources). You can specify that filenames matching certain glob-like patterns will be treated as templates and processed using the rendering engine.

Functions

Diecast ships with a suite of built-in functions that can be used to make template development easier. Check out the Diecast Function Reference for more details.

Layouts

As touched on earlier, it is often desirable for some or all of a site to share a common theme (e.g.: navigation, headers, scripts). This can be achieved in Diecast using layouts. Any files in the _layouts directory will be available as wrappers for templates. If the file _layouts/default.html exists, all templated files will be wrapped in that layout by default with no additional configuration.

A partial is a file whose name starts with an underscore (e.g: _list.html). Partials do not get layouts applied to them automatically, and are designed for making composable and dynamic pages by allowing them to be included via AJAX calls or the {{ template }} statement.

Documentation

Index

Constants

View Source
const (
	ActionSummarize BindingErrorAction = `summarize`
	ActionPrint                        = `print`
	ActionContinue                     = `continue`
	ActionBreak                        = `break`
	ActionIgnore                       = `ignore`
)
View Source
const ApplicationName = `diecast`
View Source
const ApplicationSummary = `a dynamic site generator that consumes REST services and renders static HTML output in realtime`
View Source
const ApplicationVersion = `1.9.13`
View Source
const DefaultAddress = `127.0.0.1:28419`
View Source
const DefaultConfigFile = `diecast.yml`
View Source
const DefaultRoutePrefix = `/`

Variables

View Source
var AllowInsecureLoopbackBindings bool
View Source
var Base32Alphabet = base32.NewEncoding(`abcdefghijklmnopqrstuvwxyz234567`)
View Source
var BindingClient = http.DefaultClient
View Source
var ConvertRoundToPlaces = 12
View Source
var DefaultIndexFile = `index.html`
View Source
var DefaultParamJoiner = `;`
View Source
var DefaultProxyMountTimeout = time.Duration(10) * time.Second
View Source
var DefaultTemplatePatterns = []string{`*.html`}
View Source
var DefaultVerifyFile = `/` + DefaultIndexFile
View Source
var HeaderSeparator = []byte{'-', '-', '-'}
View Source
var MaxBufferedBodySize = 16535
View Source
var MountHaltErr = errors.New(`mount halted`)

Functions

func Dir

func Dir(useLocal bool, name string) http.FileSystem

Dir returns a http.Filesystem for the embedded assets on a given prefix dir. If useLocal is true, the filesystem's contents are instead used.

func EvalInline

func EvalInline(input string, data map[string]interface{}, funcs FuncMap) string

func FS

func FS(useLocal bool) http.FileSystem

FS returns a http.Filesystem for the embedded assets. If useLocal is true, the filesystem's contents are instead used.

func FSByte

func FSByte(useLocal bool, name string) ([]byte, error)

FSByte returns the named file from the embedded assets. If useLocal is true, the filesystem's contents are instead used.

func FSMustByte

func FSMustByte(useLocal bool, name string) []byte

FSMustByte is the same as FSByte, but panics if name is not present.

func FSMustString

func FSMustString(useLocal bool, name string) string

FSMustString is the string version of FSMustByte.

func FSString

func FSString(useLocal bool, name string) (string, error)

FSString is the string version of FSByte.

func IsDirectoryError

func IsDirectoryError(err error) bool

func IsHardStop

func IsHardStop(err error) bool

func MinNonZero

func MinNonZero(data stats.Float64Data) (float64, error)

func PrettifyHTML

func PrettifyHTML(in string) (string, error)

func RegisterPostprocessor

func RegisterPostprocessor(name string, ppfunc PostprocessorFunc)

func TrimEmptyLines

func TrimEmptyLines(in string) (string, error)

Types

type Authenticator

type Authenticator interface {
	Authenticate(http.ResponseWriter, *http.Request) bool
}

type AuthenticatorConfig

type AuthenticatorConfig struct {
	Type    string                 `json:"type"`
	Paths   []string               `json:"paths"`
	Options map[string]interface{} `json:"options"`
	// contains filtered or unexported fields
}

type AuthenticatorConfigs

type AuthenticatorConfigs []AuthenticatorConfig

func (AuthenticatorConfigs) Authenticator

func (self AuthenticatorConfigs) Authenticator(req *http.Request) (Authenticator, error)

type BasicAuthenticator

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

func NewBasicAuthenticator

func NewBasicAuthenticator(options map[string]interface{}) (*BasicAuthenticator, error)

func (*BasicAuthenticator) AddPasswdFile

func (self *BasicAuthenticator) AddPasswdFile(filename string) error

func (*BasicAuthenticator) Authenticate

func (self *BasicAuthenticator) Authenticate(w http.ResponseWriter, req *http.Request) bool

type Binding

type Binding struct {
	Name               string                     `json:"name,omitempty"`
	Restrict           []string                   `json:"restrict,omitempty"`
	OnlyIfExpr         string                     `json:"only_if,omitempty"`
	NotIfExpr          string                     `json:"not_if,omitempty"`
	Method             string                     `json:"method,omitempty"`
	Resource           string                     `json:"resource,omitempty"`
	Insecure           bool                       `json:"insecure,omitempty"`
	ParamJoiner        string                     `json:"param_joiner,omitempty"`
	Params             map[string]interface{}     `json:"params,omitempty"`
	Headers            map[string]string          `json:"headers,omitempty"`
	BodyParams         map[string]interface{}     `json:"body,omitempty"`
	RawBody            string                     `json:"rawbody,omitempty"`
	Formatter          string                     `json:"formatter,omitempty"`
	Parser             string                     `json:"parser,omitempty"`
	NoTemplate         bool                       `json:"no_template,omitempty"`
	Optional           bool                       `json:"optional,omitempty"`
	Fallback           interface{}                `json:"fallback,omitempty"`
	OnError            BindingErrorAction         `json:"on_error,omitempty"`
	IfStatus           map[int]BindingErrorAction `json:"if_status,omitempty"`
	Repeat             string                     `json:"repeat,omitempty"`
	SkipInheritHeaders bool                       `json:"skip_inherit_headers,omitempty"`
	DisableCache       bool                       `json:"disable_cache,omitempty"`
	// contains filtered or unexported fields
}

func (*Binding) Evaluate

func (self *Binding) Evaluate(req *http.Request, header *TemplateHeader, data map[string]interface{}, funcs FuncMap) (interface{}, error)

func (*Binding) ShouldEvaluate

func (self *Binding) ShouldEvaluate(req *http.Request) bool

type BindingErrorAction

type BindingErrorAction string

type Engine

type Engine int
const (
	TextEngine Engine = iota
	HtmlEngine
)

func GetEngineForFile

func GetEngineForFile(filename string) Engine

func (Engine) String

func (self Engine) String() string

type FileMount

type FileMount struct {
	MountPoint  string          `json:"mount"`
	Path        string          `json:"source"`
	Passthrough bool            `json:"passthrough"`
	FileSystem  http.FileSystem `json:"-"`
}

func (*FileMount) GetMountPoint

func (self *FileMount) GetMountPoint() string

func (*FileMount) Open

func (self *FileMount) Open(name string) (http.File, error)

func (*FileMount) OpenWithType

func (self *FileMount) OpenWithType(name string, req *http.Request, requestBody io.Reader) (*MountResponse, error)

func (*FileMount) String

func (self *FileMount) String() string

func (*FileMount) WillRespondTo

func (self *FileMount) WillRespondTo(name string, req *http.Request, requestBody io.Reader) bool

type FuncMap

type FuncMap map[string]interface{}

func GetStandardFunctions

func GetStandardFunctions() FuncMap

type Mount

type Mount interface {
	Open(string) (http.File, error)
	OpenWithType(string, *http.Request, io.Reader) (*MountResponse, error)
	WillRespondTo(string, *http.Request, io.Reader) bool
	GetMountPoint() string
	String() string
}

func NewMountFromSpec

func NewMountFromSpec(spec string) (Mount, error)

type MountConfig

type MountConfig struct {
	Mount   string                 `json:"mount"`
	To      string                 `json:"to"`
	Options map[string]interface{} `json:"options"`
}

type MountResponse

type MountResponse struct {
	ContentType  string
	StatusCode   int
	Metadata     map[string]interface{}
	RedirectTo   string
	RedirectCode int
	// contains filtered or unexported fields
}

func NewMountResponse

func NewMountResponse(name string, size int64, payload interface{}) *MountResponse

func (*MountResponse) Close

func (self *MountResponse) Close() error

func (*MountResponse) GetFile

func (self *MountResponse) GetFile() http.File

func (*MountResponse) GetPayload

func (self *MountResponse) GetPayload() interface{}

func (*MountResponse) IsDir

func (self *MountResponse) IsDir() bool

func (*MountResponse) ModTime

func (self *MountResponse) ModTime() time.Time

func (*MountResponse) Mode

func (self *MountResponse) Mode() os.FileMode

func (*MountResponse) Name

func (self *MountResponse) Name() string

func (*MountResponse) Read

func (self *MountResponse) Read(p []byte) (int, error)

func (*MountResponse) Readdir

func (self *MountResponse) Readdir(count int) ([]os.FileInfo, error)

func (*MountResponse) Seek

func (self *MountResponse) Seek(offset int64, whence int) (int64, error)

func (*MountResponse) Size

func (self *MountResponse) Size() int64

func (*MountResponse) Stat

func (self *MountResponse) Stat() (os.FileInfo, error)

func (*MountResponse) Sys

func (self *MountResponse) Sys() interface{}

type PostprocessorFunc

type PostprocessorFunc func(string) (string, error)

type ProxyMount

type ProxyMount struct {
	MountPoint          string            `json:"-"`
	URL                 string            `json:"-"`
	Method              string            `json:"method,omitempty"`
	Headers             map[string]string `json:"headers,omitempty"`
	Timeout             time.Duration     `json:"timeout,omitempty"`
	PassthroughRequests bool              `json:"passthrough_requests"`
	PassthroughErrors   bool              `json:"passthrough_errors"`
	Insecure            bool              `json:"insecure"`
	Client              *http.Client
	// contains filtered or unexported fields
}

func (*ProxyMount) GetMountPoint

func (self *ProxyMount) GetMountPoint() string

func (*ProxyMount) Open

func (self *ProxyMount) Open(name string) (http.File, error)

func (*ProxyMount) OpenWithType

func (self *ProxyMount) OpenWithType(name string, req *http.Request, requestBody io.Reader) (*MountResponse, error)

func (*ProxyMount) String

func (self *ProxyMount) String() string

func (*ProxyMount) WillRespondTo

func (self *ProxyMount) WillRespondTo(name string, req *http.Request, requestBody io.Reader) bool

type Redirect

type Redirect struct {
	URL  string `json:"url"`
	Code int    `json:"code"`
}

type RedirectTo

type RedirectTo string

func (RedirectTo) Error

func (self RedirectTo) Error() string

type Server

type Server struct {
	Address             string                 `json:"address"`
	Bindings            []Binding              `json:"bindings"`
	BindingPrefix       string                 `json:"bindingPrefix"`
	RootPath            string                 `json:"root"`
	LayoutPath          string                 `json:"layouts"`
	ErrorsPath          string                 `json:"errors"`
	EnableDebugging     bool                   `json:"debug"`
	EnableLayouts       bool                   `json:"enableLayouts"`
	RoutePrefix         string                 `json:"routePrefix"`
	TemplatePatterns    []string               `json:"patterns"`
	AdditionalFunctions template.FuncMap       `json:"-"`
	TryLocalFirst       bool                   `json:"localFirst"`
	IndexFile           string                 `json:"indexFile"`
	VerifyFile          string                 `json:"verifyFile"`
	Mounts              []Mount                `json:"-"`
	MountConfigs        []MountConfig          `json:"mounts"`
	BaseHeader          *TemplateHeader        `json:"header"`
	DefaultPageObject   map[string]interface{} `json:"-"`
	OverridePageObject  map[string]interface{} `json:"-"`
	CacheDirectory      string                 `json:"cachedir"`
	PrestartCommand     StartCommand           `json:"prestart"`
	StartCommand        StartCommand           `json:"start"`
	Authenticators      AuthenticatorConfigs   `json:"authenticators"`
	// contains filtered or unexported fields
}

func NewServer

func NewServer(root string, patterns ...string) *Server

func (*Server) GetTemplateData

func (self *Server) GetTemplateData(req *http.Request, header *TemplateHeader) (FuncMap, map[string]interface{}, error)

func (*Server) GetTemplateFunctions

func (self *Server) GetTemplateFunctions(data interface{}) FuncMap

func (*Server) Initialize

func (self *Server) Initialize() error

func (*Server) InjectIncludes

func (self *Server) InjectIncludes(w io.Writer, header *TemplateHeader) error

func (*Server) ListenAndServe

func (self *Server) ListenAndServe(address string) error

func (*Server) LoadConfig

func (self *Server) LoadConfig(filename string) error

func (*Server) LoadLayout

func (self *Server) LoadLayout(name string) (io.Reader, error)

func (*Server) RunStartCommand

func (self *Server) RunStartCommand(scmd *StartCommand, waitForCommand bool) error

func (*Server) Serve

func (self *Server) Serve() error

func (*Server) ServeHTTP

func (self *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)

func (*Server) SetFileSystem

func (self *Server) SetFileSystem(fs http.FileSystem)

func (*Server) SetMounts

func (self *Server) SetMounts(mounts []Mount)

func (*Server) ShouldReturnSource

func (self *Server) ShouldReturnSource(req *http.Request) bool

func (*Server) ToTemplateName

func (self *Server) ToTemplateName(requestPath string) string

type StartCommand

type StartCommand struct {
	Command          string                 `json:"command"`
	Directory        string                 `json:"directory"`
	Environment      map[string]interface{} `json:"env"`
	WaitBefore       string                 `json:"delay"`
	Wait             string                 `json:"timeout"`
	ExitOnCompletion bool                   `json:"exitOnCompletion"`
	// contains filtered or unexported fields
}

type SwitchCase added in v1.9.9

type SwitchCase struct {
	Condition string `json:"condition,omitempty"`
	UsePath   string `json:"use,omitempty"`
}

type Template

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

func NewTemplate

func NewTemplate(name string, engine Engine) *Template

func (*Template) AddPostProcessors

func (self *Template) AddPostProcessors(postprocessors ...string) error

func (*Template) Engine

func (self *Template) Engine() Engine

func (*Template) Funcs

func (self *Template) Funcs(funcs FuncMap)

func (*Template) Parse

func (self *Template) Parse(input string) error

func (*Template) ParseFrom

func (self *Template) ParseFrom(r io.Reader) error

func (*Template) Render

func (self *Template) Render(w io.Writer, data interface{}, subtemplate string) error

func (*Template) SetEngine

func (self *Template) SetEngine(engine Engine)

func (*Template) SetHeaderOffset

func (self *Template) SetHeaderOffset(offset int)

type TemplateHeader

type TemplateHeader struct {
	Page           map[string]interface{} `json:"page,omitempty"`
	Bindings       []Binding              `json:"bindings,omitempty"`
	Defaults       map[string]string      `json:"defaults,omitempty"`
	DefaultHeaders map[string]string      `json:"default_headers,omitempty"`
	Redirect       *Redirect              `json:"redirect,omitempty"`
	Switch         []*SwitchCase          `json:"switch,omitempty"`
	Layout         string                 `json:"layout,omitempty"`
	Includes       map[string]string      `json:"includes,omitempty"`
	Headers        map[string]interface{} `json:"headers,omitempty"`
	UrlParams      map[string]interface{} `json:"params,omitempty"`
	FlagDefs       map[string]interface{} `json:"flags,omitempty"`
	Postprocessors []string               `json:"postprocessors,omitempty"`
	Renderer       string                 `json:"renderer,omitempty"`
	// contains filtered or unexported fields
}

func SplitTemplateHeaderContent

func SplitTemplateHeaderContent(reader io.Reader) (*TemplateHeader, []byte, error)

func (*TemplateHeader) Merge

func (self *TemplateHeader) Merge(other *TemplateHeader) (*TemplateHeader, error)

type Templated

type Templated interface {
	Parse(text string) error
	Funcs(FuncMap)
	Render(io.Writer, interface{}, string) error
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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