nibbler

package module
v0.3.12 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2018 License: MIT Imports: 17 Imported by: 28

README

Nibbler

CircleCI

An extension-oriented framework designed to take a lot of the boilerplate out of making a top-notch Go web server or service worker. Requires Go v1.9+.

Extensions

Extensions are the backbone of Nibbler. Extensions must implement a very simple interface (nibbler.Extension). A base class extension (NoOpExtension) is available for cases where only very few Extension methods (or none?) are required for the extension you're building.

Included Extension Categories

Nibbler also provides some extension implementations that perform common tasks for web services.

Extensions provided with Nibbler are organized by functional category, with the main Nibbler structures at the root level. These are the module categories below the root level:

  • Auth - authentication/authorization modules that do not integrate with Nibbler's user model (source of truth is not Nibbler).
  • Database - connect to databases and expose mechanisms to create, query, etc.
  • Mail - outbound email/sms/etc
  • Session - session storage and retreival
  • Storage - block/blob storage
  • User - the Nibbler user model, and various integrations that can operate with it. These will tend to be auth integrations.

Running the included sample apps

Sample apps have been provided to show how Nibbler and some extensions are used. They'll be helpful as I fill in many documentation gaps.

First, grab dependencies. If using dep, it will be with something like dep ensure or you could use something like go get -v -t -d ./...

Then, build the sample app you're interested in using (from the correct directory): go build and then run the app (from the correct directory) with go run sample.application

Note that using dep this way could pull in more vendor dependencies than your app might need (e.g. elasticsearch-related dependencies when you're using only SQL). To avoid this, use go get without the flags above (perhaps with the Gopkg.toml as a reference for the full dependency list).

Auto-wiring

To prepare for very complex apps, an auto-wiring mechanism has been added. This mechanism will take a given slice of allocated extensions and assign Extension pointer field values for each of them that is undefined, as well as order the extensions for initialization.

There are currently a few restrictions, however. The current auto-wiring implementation still has some trouble where fields are interfaces. If the field is a pointer to a struct type (e.g. *sendgrid.Extension), the auto-wiring will work fine.
Extensions like the user extension are currently trouble for auto-wiring, as the extension has a field that is an interface (which is also an extension). For now, manually wire something like this, and automatically wire everything else.

Example:

extensions := []nibbler.Extension{
    &A{},
    &A1{},
    &B1{},
    &AB{},
    &B{},
    &C{},
    &BC{},
}
exts, err := nibbler.AutoWireExtensions(&extensions, &logger)

// check error

err = app.Init(config, &logger, &extensions)

// check error

Configuration

The app configuration can be created with this method:

config, err := nibbler.LoadConfiguration(nil)

If nil is provided to the core.LoadConfiguration method, it will use environment variables for configuration of your app, with anything in ./config.json overriding it. This feature can be overridden by doing something like this in your app:

envSources := []source.Source{
    file.NewSource(file.WithPath("./config.json")),
    env.NewSource(),
}

config, err := nibbler.LoadConfiguration(&envSources)

In this case (providing nil does this), it will first apply environment variables, then apply properties from the json file (reverse order of definition). The environment variables used are upper-case but with dot-notation where the dots are replaced by underscores (e.g. nibbler.port is NIBBLER_PORT).

The following properties are available by default, but custom properties can be obtained from your extension from the Application password to it in the Init() method. For example:

(*app.GetConfiguration().Raw).Get("some", "property")

The core properties (all optional) are:

  • NIBBLER_MODE = nibbler.mode in JSON, etc, defaults to "web", but can also be "worker"
  • NIBBLER_PORT (or just PORT) = nibbler.port in JSON, etc
  • NIBBLER_DIRECTORY_STATIC = nibbler.directory.static in JSON, etc, defaults to "/public"
  • NIBBLER_AC_ALLOW_ORIGIN = nibbler.ac.allow.origin in JSON, etc, defaults to "*"
  • NIBBLER_AC_ALLOW_HEADERS = nibbler.ac.allow.headers in JSON, etc, defaults to "Origin, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Response-Time, X-PINGOTHER, X-CSRF-Token, Authorization"
  • NIBBLER_AC_ALLOW_METHODS = nibbler.ac.allow.methods in JSON, etc, defaults to "GET, POST, OPTIONS, PUT, PATCH, DELETE"

For specific configuration values for a given extension, look at the relevant module README.md.

By default, Nibbler will only pay attention to environment variables, but the sample application that ships with Nibbler shows how one might apply both environment variables and files.

A sample config example is provided "sample.config.json". There are a few things to notice:

  • both port and nibbler.port are defined. The nibbler.port value takes priority over the port value. So you will notice when the app starts that it uses nibbler.port's value when started. The "port" value (really, the PORT env var) is frequently used by PaaS providers and is often a requirement for apps and containers to register as "healthy" or "started". In any case, nibbler.port is also more explicit, so it takes priority. To experiment, set the environment variable NIBBLER_PORT to something like 8001 and start the app. You'll see that environment variables in the sample app take priority over file-defined values. If you remove all environment variables and values in the JSON file, you'll see the server start on port 3000. Your app can define sources its own way, so keep in mind the sample is just one demonstration of how this can be done.

  • the environment variables can be directly mapped to JSON values (when provided as a source to LoadConfiguration). Environment variables are all caps, and underscores are used where dots were used in the JSON format.

Logging

A simple logger must be passed to most Nibbler methods. Some simple logger implementations have been provided:

  • DefaultLogger - logs to the console
  • SilentLogger - logs nothing

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FromJson added in v0.3.9

func FromJson(jsonString string, typeOfPtr reflect.Type) (interface{}, error)

typeOfPtr should be the type of a pointer to the type you're unmarshalling to

func GetConfigurationFromSources

func GetConfigurationFromSources(sources []source.Source) (config.Config, error)

func ToJson added in v0.3.9

func ToJson(obj interface{}) (result string, err error)

func Write200Json added in v0.3.4

func Write200Json(w http.ResponseWriter, content string)

func Write404Json

func Write404Json(w http.ResponseWriter)

func Write500Json

func Write500Json(w http.ResponseWriter, message string)

Types

type Application

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

func (*Application) GetConfiguration

func (ac *Application) GetConfiguration() *Configuration

func (*Application) GetLogger

func (ac *Application) GetLogger() *Logger

func (*Application) GetRouter

func (ac *Application) GetRouter() *mux.Router

func (*Application) Init

func (ac *Application) Init(config *Configuration, logger *Logger, extensions *[]Extension) error

func (*Application) Run

func (ac *Application) Run() error

type Configuration

type Configuration struct {
	HeaderConfiguration HeaderConfiguration
	Port                int
	Raw                 *config.Config
	StaticDirectory     string
}

func LoadConfiguration added in v0.2.0

func LoadConfiguration(sources *[]source.Source) (*Configuration, error)

"merging priority is in reverse order" if nil, environment source used

type DefaultLogger

type DefaultLogger struct{}

func (DefaultLogger) Debug

func (logger DefaultLogger) Debug(message string)

func (DefaultLogger) Error

func (logger DefaultLogger) Error(message string)

func (DefaultLogger) Info

func (logger DefaultLogger) Info(message string)

func (DefaultLogger) Warn

func (logger DefaultLogger) Warn(message string)

type Extension

type Extension interface {
	Init(app *Application) error
	AddRoutes(app *Application) error
	Destroy(app *Application) error
}

func AutoWireExtensions

func AutoWireExtensions(extensions *[]Extension, logger *Logger) ([]Extension, error)

TODO: this will blow up if there's a cycle

type HeaderConfiguration

type HeaderConfiguration struct {
	AccessControlAllowHeaders string
	AccessControlAllowMethods string
	AccessControlAllowOrigin  string
}

type Logger

type Logger interface {
	Debug(message string)
	Error(message string)
	Info(message string)
	Warn(message string)
}

type NoOpExtension

type NoOpExtension struct {
}

func (*NoOpExtension) AddRoutes

func (s *NoOpExtension) AddRoutes(app *Application) error

func (*NoOpExtension) Destroy

func (s *NoOpExtension) Destroy(app *Application) error

func (*NoOpExtension) Init

func (s *NoOpExtension) Init(app *Application) error

type SilentLogger

type SilentLogger struct{}

func (SilentLogger) Debug

func (logger SilentLogger) Debug(message string)

func (SilentLogger) Error

func (logger SilentLogger) Error(message string)

func (SilentLogger) Info

func (logger SilentLogger) Info(message string)

func (SilentLogger) Warn

func (logger SilentLogger) Warn(message string)

Jump to

Keyboard shortcuts

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