pi

package module
v0.0.0-...-df3bddd Latest Latest
Warning

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

Go to latest
Published: Jun 17, 2016 License: MIT Imports: 17 Imported by: 3

README

pi

Simple toolkit for API in Go: http://godoc.org/github.com/gocarina/pi.

It offers a simple but powerful request router with interceptors to execute code before, after or when an error occurs while handling the request.

Complete Example


package main

import (
    "github.com/gocarina/pi"
)


// GetEveryUsers matches /users (GET)
func GetEveryUsers(c *pi.RequestContext) error {
    users, err := db.GetEveryUsers()
    if err != nil {
        return pi.NewError(500, err)
    }
    return c.WriteJSON(users)
}

// GetSingleUser matches /users/{id} (GET)
func GetSingleUser(c *pi.RequestContext) error {
    user, err := db.GetUserByID(c.GetRouteVariable("id"))
    if err != nil {
        return pi.NewError(400, err)
    }
    return c.WriteJSON(user)
}

// MainHandler matches / (ANY)
func MainHandler(c *pi.RequestContext) error {
    return c.WriteString("Hello, 世界")
}

// AddUser matches /users (POST)
func AddUser(c *pi.RequestContext) error {
    user := &User{}
    if err := c.GetJSONObject(user); err != nil {
        return pi.NewError(400, err)
    }
     user, err := db.AddUser(user)
     if err != nil {
        return pi.NewError(500, err)
    }
    return c.WriteJSON(user)
}

// DeleteUser matches /users/{id} and /users/{id}/delete (DELETE)
func DeleteUser(c *pi.RequestContext) error {
    if err := db.DeleteUser(c.GetRouteVariable("id")); err != nil {
        return http.NewError(404, err)
    }
    return c.WriteJSON(pi.J{"status": "OK"})
}

// AuthorizeUser will be called for each routes starting by "/users"
func AuthorizeUser(c *pi.RequestContext) error {
    // Authorize User...
    return nil
}

func main() {
    p := pi.New()
    p.Router("/",
        p.Route("/users",
            p.Route("/{id}",
                p.Route("/delete").Delete(DeleteUser)).
            Get(GetSingleUser).Delete(DeleteUser)).
        Get(GetEveryUsers).Post(AddUser).BeforeFunc(AuthorizeUser)).
    Any(MainHandler)
    
    p.ListenAndServe(":8080")
}


Documentation

Overview

Package pi is a powerful toolkit to fasten the writing of web services in Go. It has been written in top of the router from the pat toolkit (http://gorillatoolkit.org/pkg/pat).

Simple example:

import "github.com/gocarina/pi"

func main() {
	p := pi.New()
	p.Router("/",

		p.Route("/products",

				// "/products/{id}"
				p.Route("/{id}").
				Delete(DeleteProductHandler).
				Put(EditProductHandler).
				BeforeFunc(AuthorizeUser)).

		// "/products"
		Get(GetProductsHandler).
		Post(AddProductHandler))

		p.ListenAndServe(":8080")
}

This example registers two different routes :

- "/products" with two methods: GetProductsHandler (GET) and AddProductHandler (POST)

- "/products/{id}" with also two methods: DeleteProductHandler (GET) and EditProductHandler (PUT)

There is also an interceptor Before in the route "/products/{id}", that means that the function AuthorizeUser is called before calling either DeleteProductHandler or EditProductHandler.

If there was interceptors on the route "/products", it would also apply for the child routes. There is 3 kind of interceptor:

- Before: called before the request is handled by the handler. If there is an error in a Before interceptor, the request flow is stopped and Error interceptors are called.

- After: called after the request has been handled by the handled. Errors are ignored (print to the error output).

- Error: called when an error occurs in any Before interceptor or in the request handler. Errors are completely ignored.

Interceptors and Handlers are both HandlerFunction. Here is a typical example of HandlerFunction:

func SomeHandlerOrInterceptor(c *pi.RequestContext) (err error) {
	// Do something
	if err != nil {
		return pi.NewError(http.StatusInternalServerError, err) // Output: { "errorCode": 500, "errorMessage": "Message of the error" }
	}
	return c.WriteJSON(pi.J{"status": "OK"}) // Output: { "status": "OK" }
}

The RequestContext has some useful methods, please, see below for more information.

If you have any problems or questions, create an issue to our github page project: https://github.com/gocarina/pi

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrNoFiles is the error when no files is present in the value provided when
	// calling RequestContext.GetFileHeaders.
	ErrNoFiles = fmt.Errorf("no files")

	// ErrContentTypeNotSupported is the error when the format of the Content-Type is not supported
	ErrContentTypeNotSupported = fmt.Errorf("format not supported")

	// ContentTypeJSON is the default MIME for JSON data.
	ContentTypeJSON = "application/json"

	// ContentTypeXML is the default MIME for XML data.
	ContentTypeXML = "application/xml"

	// ContentTypeClassicForm is the default MIME for Form Encoded data.
	ContentTypeClassicForm = "application/x-www-form-urlencoded"

	// ContentTypeMultipart is the default MIME for Webform.
	ContentTypeMultipart = "multipart/form-data"

	// ContentTypeText is the default MIME for Textual data.
	ContentTypeText = "text/plain"
)

Functions

func SetDebug

func SetDebug(debug bool)

SetDebug sets the debugMode, logging every requests and pretty prints JSON and XML.

func SetDebugOutput

func SetDebugOutput(writer io.Writer)

SetDebugOutput sets where we need to write the output of the debug. By default, it is the standard output.

Types

type HTTPError

type HTTPError interface {
	error
	ContentType() string
	StatusCode() int
}

HTTPError represents a HTTP Error.

func NewError

func NewError(statusCode int, err error) HTTPError

NewError returns a new HTTPError, and outputs it as JSON.

func NewXMLError

func NewXMLError(statusCode int, err error) HTTPError

NewXMLError returns a new HTTPError, and outputs it as XML.

type HandlerErrorFunction

type HandlerErrorFunction func(*RequestContext, error) error

HandlerErrorFunction type is the type used by error interceptors.

type HandlerFunction

type HandlerFunction func(*RequestContext) error

The HandlerFunction type is an adapter to allow the use of ordinary functions as route handlers.

func ErrorHandler

func ErrorHandler(statusCode int) HandlerFunction

ErrorHandler returns the status code string representation and set the status code as specified. See http.StatusText.

func ServeFileHandler

func ServeFileHandler(path string, allowBrowsing bool) HandlerFunction

ServeFileHandler replies to the request with the contents of the named file or directory. For example: p := New() p.Router("/files").Get(ServeFileHandler("/tmp"))

type J

type J map[string]interface{}

J is an helper to write JSON. Example:

c.WriteJSON(pi.J{"status": "OK"})

type Pi

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

Pi represents the core of the API toolkit.

func New

func New() *Pi

New returns a new Pi.

func (*Pi) Construct

func (p *Pi) Construct()

Construct the path of the routes.

func (*Pi) ListenAndServe

func (p *Pi) ListenAndServe(addr string) error

ListenAndServe listens on the TCP network address srv.Addr and then calls Serve to handle requests on incoming connections. If srv.Addr is blank, ":http" is used.

func (*Pi) Route

func (p *Pi) Route(routeURL string, childRoutes ...*Route) *Route

Route adds a subroute to a route or router.

func (*Pi) Router

func (p *Pi) Router(routeURL string, childRoutes ...*Route) *Route

Router adds a route to the Pi router.

func (*Pi) ServeHTTP

func (p *Pi) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP serves a route in the HTTP server.

type RecovererFunction

type RecovererFunction func(*RequestContext, interface{})

RecovererFunction type is a function containing the RequestContext of the request that panicked and the value recovered.

type RequestContext

type RequestContext struct {
	W        http.ResponseWriter
	R        *http.Request
	RouteURL string
	Data     map[interface{}]interface{}
}

RequestContext represents the context of the HTTP request. It is shared across interceptors and handler.

func (*RequestContext) AddHeader

func (c *RequestContext) AddHeader(key, value string)

AddHeader adds to the response the key, value pair to the header. It appends to any existing values associated with key.

func (*RequestContext) DeleteHeader

func (c *RequestContext) DeleteHeader(key string)

DeleteHeader deletes from the response the values associated with key.

func (*RequestContext) GetAccepts

func (c *RequestContext) GetAccepts() []string

GetAccepts returns the MIME types acceptable by the caller.

func (*RequestContext) GetBody

func (c *RequestContext) GetBody() io.ReadCloser

GetBody return the body as a ReadCloser. It is the client responsibility to close the body.

func (*RequestContext) GetContentType

func (c *RequestContext) GetContentType() string

GetContentType returns the Content-Type of the request.

func (*RequestContext) GetDefaultObject

func (c *RequestContext) GetDefaultObject(object interface{}) error

GetDefaultObject calls one of a GetX method according to the Content-Type of the request. Content-Types supported:

application/json
application/xml
application/x-www-form-urlencoded
multipart/form-data

func (*RequestContext) GetFileHeaders

func (c *RequestContext) GetFileHeaders(key string) ([]*multipart.FileHeader, error)

GetFileHeaders returns an array of FileHeader. For example:

getImages := func(c *RequestContext) error {
	files, err := c.GetFileHeaders("files")
	if err != nil {
		return pi.NewError(400, err)
	}
	// Handle files
	return nil
}

p := pi.New()
p.Route("/images").Post(getImages)
p.ListenAndServe(":8080")

func (*RequestContext) GetFormObject

func (c *RequestContext) GetFormObject(object interface{}) error

GetFormObject call gorilla/schema.Decode to maps the form values of the request into the object. For more information: http://www.gorillatoolkit.org/pkg/schema

func (*RequestContext) GetHeader

func (c *RequestContext) GetHeader(key string) string

GetHeader returns the first value of the header of the request associated with the given key.

func (*RequestContext) GetHeaderOrDefault

func (c *RequestContext) GetHeaderOrDefault(key, defaultValue string) string

GetHeaderOrDefault returns the value of the header of the given defaultValue if the value is empty.

func (*RequestContext) GetHeaders

func (c *RequestContext) GetHeaders(key string) []string

GetHeaders returns the array of values associated with the key from the request.

func (*RequestContext) GetJSONObject

func (c *RequestContext) GetJSONObject(object interface{}) error

GetJSONObject call json.Unmarshal by sending the reference of the given object. For example:

func GetUser(c *pi.RequestContext) error {
	user := &User{}
	if err := c.GetJSONObject(user); err != nil {
		return pi.NewError(400, err)
	}
	// Do something with the user...
	return nil
}

func (*RequestContext) GetMultipartObject

func (c *RequestContext) GetMultipartObject(object interface{}) error

GetMultipartObject calls gocarina/formdata.Unmarshal to maps the multipart form values of the request into the object. It supports files through multipart.FileHeader.

func (*RequestContext) GetRawBody

func (c *RequestContext) GetRawBody() ([]byte, error)

GetRawBody returns the body as a byte array, closing the body reader.

func (*RequestContext) GetRouteExtraPath

func (c *RequestContext) GetRouteExtraPath() (path string)

GetRouteExtraPath returns the extra path. For example:

for route("/files"), "/files/home/user/.emacs" will return "/home/user/.emacs"

func (*RequestContext) GetRouteVariable

func (c *RequestContext) GetRouteVariable(key string) string

GetRouteVariable returns a route variable. For example:

getUserByID := func(c *RequestContext) error {
	id := c.GetRouteVariable("id")
	// Do something with the ID.
	return nil
}

p := pi.New()
p.Route("/user/{id}").Get(getUserByID)
p.ListenAndServe(":8080")

func (*RequestContext) GetURLParam

func (c *RequestContext) GetURLParam(param string) string

GetURLParam returns an URL parameter. For example, given this URL:

/user?id=1234

fmt.Println(c.GetURLParam("id"))
// Outputs 1234

func (*RequestContext) GetURLParamAsInt

func (c *RequestContext) GetURLParamAsInt(param string) int

GetURLParamAsInt returns the URL parameter as an int. Ignores error.

func (*RequestContext) GetURLParamOrDefault

func (c *RequestContext) GetURLParamOrDefault(param, defaultValue string) string

GetURLParamOrDefault returns an URL parameter or the defaultValue if the value is empty.

func (*RequestContext) GetURLParams

func (c *RequestContext) GetURLParams(param string) []string

GetURLParams returns multiple URL parameter. For example, given this URL:

/user?c=1&c=2

fmt.Println(c.GetURLParams("c"))
// Outputs [1, 2]

func (*RequestContext) GetXMLObject

func (c *RequestContext) GetXMLObject(object interface{}) error

GetXMLObject call xml.Unmarshal by sending the reference of the given object.

func (*RequestContext) SetHeader

func (c *RequestContext) SetHeader(key, value string)

SetHeader sets to the response the header entries associated with key to the single element value. It replaces any existing values associated with key.

func (*RequestContext) SetStatusCode

func (c *RequestContext) SetStatusCode(statusCode int)

SetStatusCode sets the response status code.

func (*RequestContext) WriteDefault

func (c *RequestContext) WriteDefault(object interface{}) error

WriteDefault writes the object to the caller according to the acceptable MIME in the Accept header value. If the MIME is not supported, it sends a 406 Not Acceptable request. text/plain uses the String method to be serialized. Mime supported for write:

application/json
application/xml
text/plain

If no Accept header is present, it writes the object as JSON.

func (*RequestContext) WriteJSON

func (c *RequestContext) WriteJSON(object interface{}) error

WriteJSON marshal the object to JSON and writes it via the ResponseWriter.

func (*RequestContext) WriteReader

func (c *RequestContext) WriteReader(reader io.Reader) error

WriteReader copy the reader to the ResponseWriter.

func (*RequestContext) WriteString

func (c *RequestContext) WriteString(strings ...string) error

WriteString writes the specified strings to the ResponseWriter.

func (*RequestContext) WriteTemplateFile

func (c *RequestContext) WriteTemplateFile(filename string, data interface{}) error

WriteTemplate writes the given template to the ResponseWriter.

func (*RequestContext) WriteXML

func (c *RequestContext) WriteXML(object interface{}) error

WriteXML marshal the object to XML and writes it via the ResponseWriter.

type Route

type Route struct {
	RouteURL     string
	ChildRoutes  routes
	Methods      map[string]HandlerFunction
	Interceptors interceptors
}

Route represents an API Route. For example: /user/get/{id}

func (*Route) After

func (r *Route) After(handlers ...HandlerFunction) *Route

After registers an interceptor to be called after the request has been handled.

func (*Route) AfterAsync

func (r *Route) AfterAsync(handlers ...HandlerFunction) *Route

AfterAsync registers an interceptor to be called asynchronously after the request has been handled.

func (*Route) Any

func (r *Route) Any(handlerFunc HandlerFunction) *Route

Any registers an HandlerFunction to handle any requests.

func (*Route) Before

func (r *Route) Before(handlers ...HandlerFunction) *Route

Before registers an interceptor to be called before the request is handled.

func (*Route) Custom

func (r *Route) Custom(method string, handlerFunc HandlerFunction) *Route

Custom registers an HandlerFunction to handle custom requests.

func (*Route) Delete

func (r *Route) Delete(handlerFunc HandlerFunction) *Route

Delete registers an HandlerFunction to handle DELETE requests.

func (*Route) Error

func (r *Route) Error(handlers ...HandlerErrorFunction) *Route

Error registers an interceptor to be called when an error occurs in the request handler or in any Before interceptor.

func (*Route) Get

func (r *Route) Get(handlerFunc HandlerFunction) *Route

Get registers an HandlerFunction to handle GET requests.

func (*Route) Head

func (r *Route) Head(handlerFunc HandlerFunction) *Route

Head registers an HandlerFunction to handle HEAD requests.

func (*Route) Options

func (r *Route) Options(handlerFunc HandlerFunction) *Route

Options registers an HandlerFunction to handle OPTIONS requests.

func (*Route) Patch

func (r *Route) Patch(handlerFunc HandlerFunction) *Route

Patch registers an HandlerFunction to handle PATCH requests.

func (*Route) Post

func (r *Route) Post(handlerFunc HandlerFunction) *Route

Post registers an HandlerFunction to handle POST requests.

func (*Route) Put

func (r *Route) Put(handlerFunc HandlerFunction) *Route

Put registers an HandlerFunction to handle PUT requests.

func (*Route) Recover

func (r *Route) Recover(recoverers ...RecovererFunction) *Route

Jump to

Keyboard shortcuts

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