caddycfg

package module
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2021 License: MIT Imports: 7 Imported by: 0

README

Reflect based config unmarshaler for Caddy server

It is already a part of upcoming Caddy 2: https://github.com/mholt/caddy/issues/2295

Build Status codecov GoDoc

Installation

go get github.com/sirkon/caddycfg

Usage

The usage is simple, very much like unmarshaling jsons with standard library tools:

var c *caddy.Controller
var cfg ConfigStruct

One use

if err := caddycfg.Unmarshal(c, &cfg); err != nil {
    return err
}

Got a position of plugin name in config file

head, err := caddycfg.UnmarshalHeadInfo(c, &cfg); err != nil {
    return err
}

where head is Token

type Token struct {
    File  string
    Lin   int
    Col   int
    Value string
}

Config types

Please remember, this library grows from our need to reuse our existing pieces at my job, where we use JSON configs for our microservices. That's why it needs json tag for any field. Thats is not bad. It also supports json.Unmarshaler to the certain extent — value to be decoded must come in our piece, i.e. single c.Next() or c.NextArg() footprint which is to be returned by c.Val()

Example 1

Let we have plugin called plugin.

plugin {
    key1 value1
    key2 value2
}

This can be parsed with the following structure:

type pluginConfig struct {
	Key1 string `json:"key1"`
	Key2 string `json:"key2"`
} 
Example 2

A bit harder example

plugin {
    key1 value11 value12
    key2 value2
}

This can be parsed with

type pluginConfig struct {
	Key1 []string `json:"key1"`
	Key2 string   `json:"key2"`
}
Example 3

Arguments appears before block

plugin arg1 arg2 {
    key1 value1
    key2 value2
}

This can be parsed with

type pluginConfig struct {
	caddycfg.Args
	
	Key1 string `json:"key1"`
	Key2 string `json:"key2"`
}

pluginConfig has a method Arguments from embedded type caddycfg.Args to get these positional parameters

There is also alternative approach, which needs a bit more work yet provides better control over content:

there's an interface

type ArgumentsConsumer interface {
    ConsumeArguments(head Token, args []Token) error
    Arguments() []string
}

if a structure implements it then its (of the structure) methods will be used to deal with positional parameters: method ConsumeArguments will be called to consume positional arguments at once. Note though, block is not mandatory for types implementing ArgumentsConsumer

Example 4

Internal blocks

plugin arg {
    key1 subarg {
        key value
    }
    key2 value
}

Use

type pluginConfig struct {
    caddycfg.Args
    
    Key1 subConfig `json:"key1"`
    Key2 int       `json:"key2"`
}

type subConfig struct {
    caddycfg.Args
    
    Key string `json:"key"`
}
Example 5

Parse both

plugin {
    a 1
    b 2
    c 3
}

and

plugin {
   someStrangeKeyName itsValue
}

with one type? It is easy! Just use

var target map[string]string

for this.

Example 6

Don't bother with type for simple things like

plugin a b c

?

Use

var target []string

then.

Remember, []string can also be used to unmarshal this config:

plugin {
    a
    b
    c
}

Structure validation

Data check may be needed at times. If destination type implements

type Validator interface {
	Err(head caddycfg.Token) error
}

function Err(headToken) will be called after unmarshaling

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func TokenError added in v0.0.4

func TokenError(t Token, err error) error

TokenError diagnose a error caused with a given token

func TokenErrorf added in v0.0.4

func TokenErrorf(t Token, format string, a ...interface{}) error

TokenErrorf diagnose a error caused with a given token with custom error message

func Unmarshal

func Unmarshal(c *caddy.Controller, dest interface{}) error

Unmarshal unmarshaller into dest, which must not be channel

Types

type Args

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

Args provides access to positional parameters, this is to be used to consume arguments that predate a block I mean the following; let we have a config

head arg₁ arg₂ … argₙ {
    …
}

Head is used (in case of structs) to choose a field with its type. In case if there are arguments, i.e. n > 0 followed by block (there can be no block, in this case regular []int, []string, etc is enough) the type must implement argumentAccess – this is equivalent for having type Args embedded or being type Args itself. Although it is possible to use Args itself, it will not work well enough. So, use it for embedding into your own types

func (*Args) Arguments

func (a *Args) Arguments() []string

type ArgumentsCollector added in v0.0.4

type ArgumentsCollector interface {
	AppendArgument(arg Token) error
	Arguments() []string
}

deprecated ArgumentsCollector special interface whose implementations can be used for taking arguments with additional control over the content, e.g. they can keep context to provide valuable error diagnostic. Function AppendArgument will be used to consume positional parameters in a right order and Arguments is to be used to get consumed arguments

type ArgumentsConsumer added in v0.1.0

type ArgumentsConsumer interface {
	ConsumeArguments(head Token, args []Token) error
	Arguments() []string
}

ArgumentsConsumer special interface whose implementations allows fine grain control over positional arguments Function ConsumeArguments will be used to consume all positional arguments at once

type Stream

type Stream interface {
	Next() bool
	NextArg() bool
	Token() Token
	Confirm()
}

Stream stream of tokens with so called confirmation. It works in the following way:

  1. Next checks if the previous token read was confirmed. Returns true if it is not – Token will return the

previous token. Looks for the next token and return true if it was found. Otherwise returns false.

  1. NextArg works like Next but only works for the rest of tokens in the current line
  2. Token returns token scanned with Next or NextArg
  3. Confirm confirmes scanned token was consumed

type Token

type Token struct {
	File  string
	Value string
	Lin   int
	Col   int
}

Token config token. Gives token location (Col is not supported currently)

func UnmarshalHeadInfo added in v0.0.2

func UnmarshalHeadInfo(c *caddy.Controller, dest interface{}) (Token, error)

UnmarshalHeadInfo returns token with plugin name and unmarshal c into dest

func (Token) String

func (t Token) String() string

String ...

type Validator added in v0.0.4

type Validator interface {
	Err(head Token) error
}

Validator unmarshal will call method Err of input value if input type implements this interface

Jump to

Keyboard shortcuts

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