kitchen

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

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

Go to latest
Published: Jul 27, 2015 License: MIT Imports: 7 Imported by: 0

README

kitchen

Build Status Coverage Status

A very simple bootstrap for my web project, based on alice and negroni and context package.

How?

Its very simple to handle a request in net/http package, and kitchen just add a simple middleware system to that, like this :

package main

import (
	"log"
	"net/http"

	"github.com/fzerorubigd/kitchen"
)

type midleware struct {
	next http.Handler
}

func (m *midleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	krw, ok := w.(kitchen.ResponseWriter)
	if !ok {
		panic("wtf?")
	}
	krw.SetWithValue("test", "from middleware!")

	// Call the next middleware
	m.next.ServeHTTP(w, r)
}

func newExampleMiddleware(next http.Handler) http.Handler {
	return &midleware{next}
}

func main() {

	req := func(w http.ResponseWriter, r *http.Request) {
		krw, ok := w.(kitchen.ResponseWriter)
		if !ok {
			panic("wtf?")
		}
		test, ok := krw.Context().Value("test").(string)
		if !ok {
			panic("wtf?")
		}

		w.Write([]byte(test))
	}

	http.Handle(
		"/",
		kitchen.NewChain(newExampleMiddleware).ThenFunc(req),
	)

	log.Fatal(http.ListenAndServe(":9091", nil))
}

the middleware system, always add a responseWriterWrap middleware at the begining, so the first argument is always kitchen.ResponseWriter. The default context is a cancel context and after finishing the request, the cancel function is triggered and you can watch for Done channel in Context() if you need to know the request is delivered and its time to give up.

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/fzerorubigd/kitchen"
)

type midleware struct {
	next http.Handler
}

func (m *midleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	krw, ok := w.(kitchen.ResponseWriter)
	if !ok {
		panic("wtf?")
	}

	start := time.Now()
	log.Println("New request...")

	go func() {
		<-krw.Context().Done()
		latency := time.Since(start)
		log.Println(r.URL.Path, krw.Status(), krw.Context().Err(), latency)
	}()

	m.next.ServeHTTP(w, r) // Call the next one
}

func newExampleMiddleware(next http.Handler) http.Handler {
	return &midleware{next}
}

func main() {

	req := func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("See terminal for log."))
	}

	http.Handle(
		"/",
		kitchen.NewChain(newExampleMiddleware).ThenFunc(req),
	)

	log.Fatal(http.ListenAndServe(":9091", nil))
}

See this article about context.

There is some example, not fully tested middleware in middlewares sub package, but just use them as example, anything may change there.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Chain

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

Chain structure for handling middleware This is base on alice. I think alice is good but whitout call(next(next(next))), I think this is not a good thing to have this kind of chain. also the ResponseWriter need more extra Data to handle

func NewChain

func NewChain(f ...Middleware) Chain

NewChain create new middleware chain base on provided middlewares function

func (Chain) Extend

func (mc Chain) Extend(f ...Middleware) Chain

Extend Append function to middleware chain and return NEW chain object The old chain is usable after this.

func (Chain) Then

func (mc Chain) Then(h http.Handler) http.Handler

Then Create the real http handler function.

func (Chain) ThenFunc

func (mc Chain) ThenFunc(fn http.HandlerFunc) http.Handler

ThenFunc Create the real http handler function.

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware is the call back used for middlewares

type ResponseWriter

type ResponseWriter interface {
	// The original response writer
	http.ResponseWriter
	// Flusher interface
	http.Flusher
	// Hijacker is used in websocket connections and al upgrade request
	http.Hijacker
	//The status code set by the client
	Status() int
	// How many byte written into this writer
	Size() int
	// Is the output is written already or not?
	Written() bool
	// Get the current context
	Context() context.Context
	// Set the context with a value
	SetWithValue(key interface{}, value interface{})
	// Set the context with timeout
	SetWithTimeout(time.Duration) context.CancelFunc
	// Set the context with deadline
	SetWithDeadline(time.Time) context.CancelFunc
}

ResponseWriter is much like negroni ResponseWriter interface. But it also support context, using google context package, the context is readonly and can extend it with SetWith* functions

func NewResponseWriter

func NewResponseWriter(rw http.ResponseWriter, ctx context.Context) ResponseWriter

NewResponseWriter Create new response writer base on http response writer interface TODO : do i need to implement hijacker and flusher interface?

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

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