medeina

package module
Version: v0.0.0-...-642dbf2 Latest Latest
Warning

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

Go to latest
Published: Jan 17, 2015 License: MIT Imports: 7 Imported by: 1

README

Medeina Build Status GoDoc Coverage Status docs examples dependencies

Medeina is a Go routing tree based on HttpRouter and inspired by Ruby's Roda and Cuba. It allows to define the HTTP routes of your web application as a tree, operating on the current route at any point of the tree.

As stated in Roda's website, "this allows you to have much DRYer code". All the routes can have all the features of HttpRouter: named paramaters, catch-all parameters, etc.

Actually, Medeina inherits all the performance and flexibility you love in HttpRouter (great job, Julien!).

Status

Medeina is fully functional and tested but it's still green and young. It may lack some useful functionality. If you use HttpRouter, give Medeina a try. All real world experience is welcome.

Install

go get github.com/imdario/medeina

// use in your .go code
import (
    "github.com/imdario/medeina"
)

Usage

Check the docs and these examples:

// From Roda's site
r := medeina.NewMedeina()
r.GET(func() {
    r.Is("", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
        http.Redirect(w, r, "/hello", http.StatusFound)
    })
    r.On("hello", func() {
        r.Is("world", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
            fmt.Fprintf(w, "Hello world!")
        })
        r.Is("", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
            fmt.Fprintf(w, "Hello!")
        })
    })
})

log.Fatal(http.ListenAndServe(":8080", r))

And this for a quick and dirty "REST-like" API (ignore the fact that I'm using a single method to handle everything):

endpoints := []string {
    "department", "employee", "project"
}
r := medeina.NewMedeina()
r.GET(func() {
    r.Is("", Index)
})
for endpoint := range endpoints {
    r.On(endpoint, func() {
        r.GET(func() {
            r.Is(":id", Model)
        })
        r.POST(func() {
            r.Is("", Model)
        })
        r.PUT(func() {
            r.Is("", Model)
        })
        r.DELETE(func() {
            r.Is(":id", Model)
        })
    })
}

log.Fatal(http.ListenAndServe(":8080", r))

Or it's "shorter" (YMMV) form:

endpoints := []string {
    "department", "employee", "project"
}
r := medeina.NewMedeina()
r.Is("", Index, medeina.GET)
for endpoint := range endpoints {
    r.On(endpoint, func() {
        r.Is("", Model, medeina.POST, medeina.PUT)
        r.Is(":id", Model, medeina.GET, medeina.DELETE)
    })
}

log.Fatal(http.ListenAndServe(":8080", r))

What does "" means? It matches the current path in your route. It's a way to easily match the scope itself as canonical URL.

Why HttpRouter?

Because it's the most fast and flexible Go HTTP router around the town and a good one to start. If you want Medeina to work with your preferred option, patches are welcome!

If you don't know HttpRouter, please check it out. You won't regret it.

Why is it called Medeina?

From Wikipedia:

Medeina or Medeinė (derived from medis (tree) and medė (forest)), [...] is one of the main deities in the Lithuanian mythology, similar to Latvian Meža Māte. She is a ruler of forests, trees and animals. Her sacred animal is a hare.

Hey, we were talking about trees. It fits right! Also, this project can join my other ones, also called by names starting by 'm': Mergo, Minshu, mqqsig192, etc. Don't ask, it wasn't on purpose.

Contact me

If I can help you, you have an idea or you are using Medeina in your projects, don't hesitate to drop me a line (or a pull request): @im_dario

About

Written by Dario Castañé.

License

MIT license.

Documentation

Overview

Medeina is a routing tree based on httprouter inspired by Ruby's Roda and Cuba. It allows to define your routes as a tree, operating on the current one at any point of the routing tree.

Usage

// From Roda's site
r := medeina.NewMedeina()
r.GET(func() {
	r.Is("", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		http.Redirect(w, r, "/hello", http.StatusFound)
	})
	r.On("hello", func() {
		r.Is("world", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
			fmt.Fprintf(w, "Hello world!")
		})
		r.Is("", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
			fmt.Fprintf(w, "Hello!")
		})
	})
})

If you want to check a more convoluted example, feel free to check github_test.go. It uses several possible styles of creating routes using Medeina in order to avoid pitfalls.

Copyright (c) 2014 Dario Castañé. Licensed under the MIT License.

Copyright (c) 2015 Dario Castañé. Licensed under the MIT License. From httprouter's example.

Index

Constants

View Source
const (
	GET    = "GET"
	POST   = "POST"
	PUT    = "PUT"
	PATCH  = "PATCH"
	DELETE = "DELETE"
)

Variables

View Source
var Methods = []Method{GET, POST, PUT, PATCH, DELETE}

Functions

func HandlerPathPrefix

func HandlerPathPrefix(prefix string, handle http.Handler) http.Handler

Utility function to use with http.Handler compatible routers. Modifies the request's URL in order to make subrouters relative to the prefix. If you use a router as subrouter without this they need to match the full path.

Types

type Handle

type Handle func()

Medeina closures definition.

type HostSwitch

type HostSwitch map[string]http.Handler

We need an object that implements the http.Handler interface. Therefore we need a type for which we implement the ServeHTTP method. We just use a map here, in which we map host names (with port) to http.Handlers

func (HostSwitch) ServeHTTP

func (hs HostSwitch) ServeHTTP(w http.ResponseWriter, r *http.Request)

Implement the ServerHTTP method on our new type

type Medeina

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

Medeina is a goddess willing to help you with your trees... of routes. Allow it to be part of your chain of HTTP Handlers and she will handle all those messy branches that your once-used-to-be-simple router got.

func NewMedeina

func NewMedeina() *Medeina

Returns a new initialized Medeina tree routing with default httprouter's one.

func (*Medeina) DELETE

func (m *Medeina) DELETE(handles Handle)

Switches context to use DELETE method as default in the closure.

func (*Medeina) GET

func (m *Medeina) GET(handles Handle)

Switches context to use GET method as default in the closure. You can override for a route while using Is, setting which methods you want.

func (*Medeina) Handler

func (m *Medeina) Handler(path string, handle http.Handler, methods ...Method)

As Is but delegateing on a standard http.Handler. There is no equivalent functions for specific HTTP methods, so you must use this in order to add standard http.Handlers.

func (*Medeina) Is

func (m *Medeina) Is(path string, handle httprouter.Handle, methods ...Method)

Sets a canonical path. A canonical path means no further entries are in the path.

func (*Medeina) On

func (m *Medeina) On(path string, handle Handle)

Adds a new subpath to the current context. Everything under the closure will use all the previously set path as root for their URLs.

func (*Medeina) OnFunc

func (m *Medeina) OnFunc(path string, handle func(*Medeina))

As On but using a function which accepts a routing tree as parameter. This will be useful to split routes definition in several functions.

func (*Medeina) OnHandler

func (m *Medeina) OnHandler(path string, handle http.Handler)

As On but using a function which accepts a standard http.Handler, delegating further route handling to the handler. It adds a HttpRouter catch-all matcher called 'medeina_subpath'. This will be useful to split routes definition in several functions.

func (*Medeina) OnMux

func (m *Medeina) OnMux(path string, handle http.Handler)

As OnHandler for subrouters. It's a convenience function. These two calls are equivalent:

m.OnHandler("api/v1/events", HandlerPathPrefix("/api/v1/events", mux)) m.OnMux("api/v1/events", mux)

func (*Medeina) PATCH

func (m *Medeina) PATCH(handles Handle)

Switches context to use PATCH method as default in the closure.

func (*Medeina) POST

func (m *Medeina) POST(handles Handle)

Switches context to use POST method as default in the closure.

func (*Medeina) PUT

func (m *Medeina) PUT(handles Handle)

Switches context to use PUT method as default in the closure.

func (*Medeina) ServeHTTP

func (m *Medeina) ServeHTTP(w http.ResponseWriter, r *http.Request)

Makes the routing tree implement the http.Handler interface.

type Method

type Method string

HTTP Methods available as constants. We could use strings but it was cleaner to force specefic values in an enum-like fashion.

type Params

type Params httprouter.Params

Jump to

Keyboard shortcuts

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