ruller

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2020 License: MIT Imports: 19 Imported by: 1

README

ruller

Build Status

A simple REST based rule engine in which rules are written in Go

  1. You create and register some rules as Go functions in a "main" program and run it
  2. You POST to /rules/[group-name] along with some JSON body.
  3. All rules for that group are processed using the request body.
  4. Depending on your implementation, some rules returns data and some rules not.
  5. Finally, all rule's results are merged and returned to the REST caller as a JSON.
  6. You can websocket connect to /ws in order to detect server restarts. This is a dummy websocket server.

Ruller works by invoking a bunch of rules with the same input from a single REST call, merging rules outputs and returning the result to the caller.

You can use this for feature enablement, dynamic systems configuration and other applications where a static key value store wouldn't help you because you need some logic on an input value in order to determine the output.

Checkout some benchmarks we made this far too.

Example

Checkout the ruller-sample project.

Special parameters on POST body

  • "_flatten" - true|false. If true, a flat map with all keys returned by all rules, with results merged, will be returned. If false, will return the results with the same tree shape as the rules itself. Defaults to true

  • "_keepFirst" - true|false. When using flat map as result, this determines whetever to keep the value from the first or the last rule processed during merge. Default is true

  • "_info" - true|false. If true, will add the attribute "_rule" with the name of the rule that generated the node on the result tree (if not using flat map as result). Default to true

Input parameters used as rules input

  • The POST body JSON elements will be converted to a map and used as input parameters

  • Additionally, "_remote_ip" is set with client remote address

  • If you define a geolite2 database using "--geolite2-db", Ruller will use GeoLite to determine City and Country names corresponding to client IP. It will determine the source IP by first looking at the "X-Forwarded-For" header. If not present, it will use the IP of the direct requestor.

  • When Geolite is activated, the following attributes will be placed on input:

    • "_ip_country": Country name
    • "_ip_city": City name
    • "_ip_longitude": Longitude
    • "_ip_latitude: Latitude
    • "_ip_accuracy_radius: Accuracy radius
  • When you pass a csv file in format "[country iso code],[City],[State]" using "--city-state-db", you will have an additional input:

    • "_ip_state: State based on city info
  • You can define required inputs along with their associated types so that before processing rules Ruller will perform a basic check if they are present (ruller.AddRequiredInput(..)). This is usedful so that you don't have to perform those verifications inside each rule, as it was already verified before executing the rules.

Request/Response filtering

  • ruller.setRequestFilter(func(r *http.Request, input map[string]interface{}) error { return nil })

    • You can verify http request attributes and change input map as you need
  • func(w http.ResponseWriter, input map[string]interface{}, output map[string]interface{}, outBytes []byte) (bool, error) {return false, nil}

    • You can verify the input and output map and write something to the response. If you return true, the default JSON marshal that ruller performs will be skipped.
  • See an example at sample/main.go

More resources

  • http://github.com/flaviostutz/ruller-sample-feature-flag - an example on how to build a DSL tool to generate Go Ruller code from a JSON and to build a Docker container with the REST api for your compiled rules. Has various functions for common scenarios of feature flags management

Thanks, Maxmind!

This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Add

func Add(groupName string, ruleName string, rule Rule) error

Add adds a rule implementation to a group

func AddChild

func AddChild(groupName string, ruleName string, parentRuleName string, rule Rule) error

AddChild adds a rule implementation to a group

func AddRequiredInput

func AddRequiredInput(groupName string, inputName string, it InputType)

AddRequiredInput adds a input attribute name that is required before processing the rules

func HandleRuleGroup added in v1.0.1

func HandleRuleGroup(w http.ResponseWriter, r *http.Request)

func Process

func Process(groupName string, input map[string]interface{}, options ProcessOptions) (map[string]interface{}, error)

Process process all rules in a group and return a resulting map with all values returned by the rules

func SetDefaultFlatten

func SetDefaultFlatten(groupName string, value bool)

SetDefaultFlatten sets whatever to flatten output or keep it hierarchical. This may be overriden during rules evaluation with a "_flatten" attribute in input

func SetDefaultKeepFirst

func SetDefaultKeepFirst(groupName string, value bool)

SetDefaultKeepFirst sets whatever to keep the first or the last occurence of an output attribute when flattening the output. This may be overriden during rules evaluation with a "_keepFirst" attribute in input

func SetRequestFilter

func SetRequestFilter(rf RequestFilter)

SetRequestFilter set the function that will be called at every call

func SetResponseFilter

func SetResponseFilter(rf ResponseFilter)

SetResponseFilter set the function that will be called at every call with output. If returns true, won't perform the default JSON renderization

func StartServer

func StartServer() error

StartServer Initialize and start REST server

Types

type Context

type Context struct {
	Input          map[string]interface{}
	ChildrenOutput map[string]interface{}
}

Context used as input for rule processing

type InputType

type InputType int

InputType input type for required input names declaration

const (
	//String input type
	String InputType = iota
	//Float64 input type
	Float64
	//Bool input type
	Bool
)

type ProcessOptions

type ProcessOptions struct {
	//MergeKeepFirst When merging output results from rules, if there is a duplicate key, keep the first or the last result found. applies when using flatten output. defaults to true
	MergeKeepFirst bool
	//AddRuleInfo Add rule info attributes (name etc) to the output tree when not flatten. defaults to false
	AddRuleInfo bool
	//Get all rules's results and merge all outputs into a single flat map. If false, the output will come the same way as the hierarchy of rules. Defaults to true
	FlattenOutput bool
}

ProcessOptions options for rule process

type RequestFilter

type RequestFilter func(r *http.Request, input map[string]interface{}) error

RequestFilter Function called on every HTTP call before rules processing. params: request, input attributes returns: error

type ResponseFilter

type ResponseFilter func(w http.ResponseWriter, input map[string]interface{}, output map[string]interface{}, outBytes []byte) (bool, error)

ResponseFilter Function called on every HTTP call after rules processing. params: http response writer, input attribute, output attributes. returns: bool true if ruller should interrupt renderization and rely on what the filter did, error

type Rule

type Rule func(Context) (map[string]interface{}, error)

Rule Function that defines a rule. The rule accepts a map as input and returns a map as output. The output map maybe nil

Jump to

Keyboard shortcuts

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