thinkoner/thinkgo

View on GitHub
router/pipeline.go

Summary

Maintainability
A
0 mins
Test Coverage
package router

import (
    "container/list"

    "github.com/forgoer/thinkgo/context"
)

type Pipeline struct {
    handlers []Middleware
    pipeline *list.List
    passable *context.Request
}

// Pipeline returns a new Pipeline
func NewPipeline() *Pipeline {
    p := &Pipeline{
        pipeline: list.New(),
    }
    return p
}

// Pipe Push a Middleware Handler to the pipeline
func (p *Pipeline) Pipe(m Middleware) *Pipeline {
    p.pipeline.PushBack(m)
    return p
}

// Pipe Batch push Middleware Handlers to the pipeline
func (p *Pipeline) Through(hls []Middleware) *Pipeline {
    for _, hl := range hls {
        p.Pipe(hl)
    }
    return p
}

// Passable set the request being sent through the pipeline.
func (p *Pipeline) Passable(passable *context.Request) *Pipeline {
    p.passable = passable
    return p
}

// Run run the pipeline
func (p *Pipeline) Run(destination Middleware) interface{} {
    var result interface{}

    p.Pipe(destination)

    e := p.pipeline.Front()
    if e != nil {
        result = p.handler(p.passable, e)
    }
    return result
}

func (p *Pipeline) handler(passable *context.Request, e *list.Element) interface{} {
    if e == nil {
        return nil
    }
    middleware := e.Value.(Middleware)
    result := middleware(passable, p.closure(e))
    return result
}

func (p *Pipeline) closure(e *list.Element) Closure {
    return func(req *context.Request) interface{} {
        e = e.Next()
        return p.handler(req, e)
    }
}