Giter Club home page Giter Club logo

pastis's Introduction

pastis GoDoc

Go framework for developing ops-friendly RESTful web services

Getting Started

Pastis is a framework for creating RESTful web services with minimal effort:

Quick Example

//main.go
package main

import "net/url"
import "github.com/guregodevo/pastis"

func main() {
	api := pastis.NewAPI()
	api.Get("/foo",  func() (int, interface{}) {
		return 200, "Hello"
	})
	api.Start(4567)
}

And run with:

go run main.go

View at: http://localhost:4567/foo

Installing

Using go get

$ go get github.com/guregodevo/pastis

After this command pastis is ready to use. Its source will be in:

$GOROOT/src/pkg/github.com/guregodevo/pastis

You can use go get -u -a to update all installed packages.

Routes

In Pastis, a route is an HTTP method paired with a URL-matching pattern. Each route is associated with a callback function:

	api.Get("/foo", func(params url.Values) (int, interface{}) {
		...show something
	})

	api.Post("/foo", func(params url.Values) (int, interface{}) {
		...create something
	})

	api.Put("/foo", func(params url.Values) (int, interface{}) {
		...modify something
	})

	api.Patch("/foo", func(params url.Values) (int, interface{}) {
		...modify something
	})

	api.Delete("/foo", func(params url.Values) (int, interface{}) {
		...delete something
	})

	api.Link("/foo", func(params url.Values) (int, interface{}) {
		...affiliate something
	})

	api.Unlink("/foo", func(params url.Values) (int, interface{}) {
		...separate something
	})

Routes are matched in the order they are defined. The first route that matches the request is invoked.

In Pastis, query or path parameters are both accessible via the optional callback parameter of type url.Values.

Route patterns may include **named parameters:

	api.Get("/posts/:title", func(params url.Values) (int, interface{}) {
		title := params.Get("title")
                ...show something with this named parameter
	})

Routes may also utilize **query parameters:

	api.Get("/posts", func(params url.Values) (int, interface{}) {
		title := params.Get("title")
		author := params.Get("author")
		greeding := fmt.SPrintf("Hello %s", name)	
		// uses title and author variables; query is optional to the /posts route
	})

Routes may require the request body. In Pastis, the request body is decoded to the type of the callback parameter that you declared as input parameter in the callback. Any parameter that has a type different from url.Values will match the request body content provided that it can be represented as valid JSON.

Possible request body parameter can be any of the following types:

  • map[string]interface{} or struct (those that begin with uppercase letter) for JSON Objects
  • []interface{} for JSON arrays
  • Any Go primitive type that matches the body content that is more convenient that the type above (int, string etc..)

Return Values

Every callback execution should end up returning a tuple (int, interface{}). The tuple element of type int represents the HTTP status code. The other one of type interface{} represents the response content. The return handler will take care of marshalling this content into JSON.

Examples:

	return http.StatusOK, [] Chart{Chart{"name", 1},Chart{"name", 1}}
	return http.StatusCreated, Identifier{params.Get("id"), 2}
	return http.StatusCreated, map[string]interface{} {"id":1, "size":3, "type":"line"}
	return http.StatusOK, "Hello"

Resources

In Pastis, a resource is any Go struct that implements HTTP methods (GET, PUT etc..).

type DashboardResource struct {
}

type ChartResource struct {
}

type Chart struct {
	Name  string
	Order int
}

func (api DashboardResource) Get(params url.Values) (int, interface{}) {
	...do something with params params.Get("dashboardid")	
	return http.StatusOK, [] Chart{Chart{"name", 1},Chart{"name", 1}}
}

func (api ChartResource) Get(params url.Values) (int, interface{}) {
	return http.StatusOK, Chart{params.Get("chartid"), 2}
}

func (api ChartResource) Put(params url.Values) (int, interface{}) {
	...do something with params params.Get("chartid")
}

A resource has a unique URL-matching pattern. Therefore, each resource route method is associated with the resource method function whose name matches.

dashboardResource := new(DashboardResource)
chartResource := new(ChartResource)
api := NewAPI()
api.AddResource("/dashboards/:dashboardid", dashboardResource)
api.AddResource("/dashboards/:dashboardid/charts/:chartid", chartResource )
api.Start(44444)

In the above example, the chart resource Put method matches the HTTP method "PUT" and the resource URL "/dashboards/:dashboardid/charts/:chartid".

Resource method functions behave exactly like callback method except that they match the resource route.

Filters

Filters are evaluated before and/or after request within the same context as the routes will be and can modify the request and response.

A filter is any function that sastifies this interface :

type Filter func(http.ResponseWriter, *http.Request, *FilterChain)


// Filter (post-process) Filter (as a struct that defines a FilterFunction)
func LoggingFilter(w http.ResponseWriter, request *http.Request, chain *FilterChain) {
	now := time.Now()
	chain.NextFilter(w, request)
	log.Printf("[HTTP] %s %s [%v]\n", request.Method, request.URL, time.Now().Sub(now))
}

Any filter can be added to apis

	var api = pastis.NewAPI()
	api.AddFilter(pastis.LoggingFilter)

CORS Support

Pastis provides CORS filter. If you need it, just add the CORS filter to your api.

	var api = pastis.NewAPI()
	api.AddFilter(pastis.CORSFilter)

Testing

Pastis tests can be written using any testing library or framework. The native Go package httptest is recommended:

import (
	"net/http/httptest"
	"reflect"
	"testing"
)

/* Test Helpers */
func expect(t *testing.T, a interface{}, b interface{}) {
	....
}


func assert_HTTP_Response(t *testing.T, res *http.Response, expectedStatusCode int, expectedResponsebody interface{}) {
	....
}

func Test_Callback_With_Params(t *testing.T) {
	p := NewAPI()
	p.Get( "/hello/:name", func(params url.Values) (int, interface{}) {
		fmt.Printf("Name : %v",params.Get("name"))
		return http.StatusOK, Foo { params.Get("name"), 1 }
	})
	p.HandleFunc()

	ts := httptest.NewServer(p)
	defer ts.Close()

	url := ts.URL + "/hello/guregodevo"
	res, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}
	assert_HTTP_Response(t, res, http.StatusOK, Foo{"guregodevo", 1})
}

Logging

Pastis includes its own logging API. It allows the developer to control which log statements are output with arbitrary granularity. It is fully configurable at runtime.

Pastis Logger may be assigned a minimum level. The set of possible levels, in ascending order is:

  • DEBUG,
  • INFO,
  • WARN,
  • ERROR and
  • FATAL
  • OFF

A logger minimum level enables any log message whose level order is equals or lower.

By default, this API Logger level is "DEBUG" and the log output stream is StdOut.

//main.go
package main

import "net/url"
import "github.com/guregodevo/pastis"
import "os"
func main() {
	api := pastis.NewAPI()
	api.SetLevel("INFO")
	api.SetOutput("ERROR", os.Stderr, log.Ltime)
	//ERROR logs will now be printed out to the standard error stream
	//Prefixed by ERROR and the time flag "ERROR 01:23:23" 
}

JSON

Pastis speaks JSON. In terms of data formats, JSON has become mainstream, and the package encoding/json is fairly robust in the Go programming language. In addition to being lightning fast, it has a sophisticated mashaller, allowing you to use type safe parameter when recieving request content.

In the example below, the body content of the request is fully decoded using the Go JSON decoder. Pastis just takes care of detecting the parameter type and unmarshalling it.

//main.go
package main

import "net/url"
import "github.com/guregodevo/pastis"
import "fmt"

type Foo struct {
	Name string
	Order int	
}

func main() {
	api := pastis.NewAPI()
	api.Post( "/foo", func(vals url.Values, body Foo) (int, interface{}) {
		fmpt.Printf("Here is the request body %v ", foo)
		return http.StatusOK, body
	})
}

pastis's People

Contributors

bryant1410 avatar guregodevo avatar peterhellberg avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.