service

package
v0.0.0-...-b22b293 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2016 License: MIT Imports: 7 Imported by: 0

README

Services in Mash

By default, Mash provides no built-in tasks, and instead acts as host to services, self-contained pieces of code that attach themselves to Mash according to a minimal set of rules.

Structure

A service consists of a folder containing any number of go files in a package named after the folder in which the files are contained. The package defines a custom type, which is registered with Mash, and methods attached to that type which correspond to available tasks within that service.

Sample Service

In order to demonstrate the rules required for writing a service, we are going to build a sample service named helloworld, which defines two tasks, one which responds with "Hello World!" and another which responds with "Goodbye World!".

The service also defines a configuration variable name which overrides the default value of "World" and allows the service to respond with a custom name (e.g. "Hello Alex!").

package helloworld

import (
	"flag"
	"fmt"
	"net/http"

	"github.com/deuill/mash/service"
)

type Helloworld struct {
	Name *string
}

func (h *Helloworld) Hello(w http.ResponseWriter, r *http.Request, p service.Params) (*service.Response, error) {
	if *h.Name == "" {
		return "", fmt.Errorf("Name is empty!")
	}

	return &service.Response{http.StatusOK, "Hello " + *h.Name + "!"}, nil
}

func (h *Helloworld) Goodbye(w http.ResponseWriter, r *http.Request, p service.Params) (*service.Response, error) {
	if *h.Name == "" {
		return "", fmt.Errorf("Name is empty!")
	}

	return &service.Response{http.StatusOK, "Goodbye " + *h.Name + "!"}, nil
}

func init() {
	flags := flag.NewFlagSet("helloworld", flag.ContinueOnError)
	serv := &Helloworld{
		Name: flags.String("name", "World", ""),
	}

	service.Register("helloworld", flags, []service.Handler{
		{"GET", "/hello", serv.Hello},
		{"GET", "/goodbye", serv.Goodbye},
	})
}

Services contain a minimal amount of boilerplate in order to be functional. These are as follows:

type ServiceName interface{}

The method receiver (in this case, the Helloworld struct) can be any valid receiver type, including an empty structure. This receiver is then used to register any attached methods to the service host, as explained below.

func init()

This method contains, minimally, a call to service.Register() for attaching the method receiver and any exported methods to the service host. Although technically possible, it is not recommended to attach more than one method receiver per package.

Any command-line options are also declared here, and become available under the global configuration scheme.

Handling requests

After all registered services complete their initialization routine, the service host initializes its internal HTTP server and begins accepting requests on a specified TCP port (default is 6116).

Methods registered using service.Register are made available under their service name, followed by the path specified in their Handler type. Paths are matched according to rules specified in the httprouter Documentation.

So, for the example calls above, you would get the following URL endpoints, for a local server running with the default options:

http://localhost:6116/helloworld/hello
http://localhost:6116/helloworld/goodbye

Any method registered in this way is expected to correspond to the following declaration:

func (*ServiceName) MethodName(http.ResponseWriter, *http.Request, service.Params) (*service.Response, error)

Methods can handle any arguments bound to the HTTP request via the service.Params type, which allows you to fetch named parameters via the Params.Get method, or on their own using the http.Request type.

Returning data to the user can be accomplished by returning any non-nil service.Response type, in which case the values are encoded as JSON before being returned, or manually through the http.ResponseWriter type, in which case the method is expected to return nil for the service.Response type.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Init

func Init() error

Initialize service host, including internal HTTP service.

func Register

func Register(name string, flags *flag.FlagSet, handlers []Handler) error

Register service for use with Mash.

Types

type HandleFunc

type HandleFunc func(http.ResponseWriter, *http.Request, Params) (*Response, error)

A HandleFunc represents the default signature for registered methods attached to services.

type Handler

type Handler struct {
	Method string     // The HTTP method handler is attached under, e.g. GET, POST, DELETE etc.
	Path   string     // The request path to bind handler against. Supports parameter bindings.
	Handle HandleFunc // The method to use for this handler.
}

Handler represents a registered handler method attached to Mash.

type Params

type Params httprouter.Params

Params are attached to methods according to their path declarations, and may contain values corresponding to named parameters declared on those paths.

func (Params) Get

func (p Params) Get(name string) string

Get returns the value corresponding to a named parameter. It returns an empty string if no value was found.

type Response

type Response struct {
	Code int         // The HTTP response code.
	Data interface{} // The data to serialize to JSON.
}

Response represents a JSON response, containing a response code and serialise-able data.

Directories

Path Synopsis
ico

Jump to

Keyboard shortcuts

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