package main
import (
"context"
"errors"
"fmt"
"log"
"net/http"
)
type Request struct {
Data string
Name string
Upload string
}
type Response struct {
}
type Context struct {
Req *Request
Resp *Response
handlers []FilterFunc
index int
}
func (c *Context) Next() error {
c.index++
s := len(c.handlers)
for ; c.index <= s; c.index++ {
if err := c.handlers[c.index-1](c); err != nil {
return err
}
}
return nil
}
type Filter interface {
Handle(ctx *Context) error
}
type FilterFunc func(ctx *Context) error
type FilterDecorator struct {
filters []FilterFunc
}
func NewFilterDecorator() *FilterDecorator {
return &FilterDecorator{}
}
func (d *FilterDecorator) Use(middlewares ...FilterFunc) {
d.filters = append(d.filters, middlewares...)
}
func (d *FilterDecorator) Do(request *Request, response *Response) error {
c := new(Context)
c.Req = request
c.Resp = response
c.handlers = d.filters
return c.Next()
}
func ValidateParam() FilterFunc {
return func(ctx *Context) error {
req := ctx.Req
if req.Name != "Tom" {
return errors.New("name is not Tom")
}
ctx.Next()
return nil
}
}
func ProcessFilter() FilterFunc {
return func(ctx *Context) (err error) {
log.Println("processing ProcessFilter")
defer func() {
log.Println("after ProcessFilter")
}()
ctx.Req.Name = "Jack"
if err := ctx.Next(); err != nil {
return err
}
return nil
}
}
type Uploader interface {
Upload(ctx context.Context, data string) error
}
type UploaderFunc func(ctx context.Context, data string) error
func (u UploaderFunc) Upload(ctx context.Context, data string) error {
return u(ctx, data)
}
type AliyunClient struct {
c *http.Client
}
func NewAliyunClient() *AliyunClient {
return &AliyunClient{}
}
func (a *AliyunClient) Upload(ctx context.Context, data string) error {
log.Printf("AliyunClient Upload:%s", data)
return nil
}
type AwsClient struct {
c *http.Client
}
func NewAwsClient() *AwsClient {
return &AwsClient{}
}
func (a *AwsClient) Upload(ctx context.Context, data string) error {
log.Printf("AwsClient Upload:%s", data)
return nil
}
func AzureUpload() UploaderFunc {
return func(ctx context.Context, data string) error {
log.Printf("AzureClient Upload:%s", data)
return nil
}
}
func UploadFilter() FilterFunc {
aliyun := NewAliyunClient()
aws := NewAwsClient()
uploaderMap := map[string]Uploader{
"aliyun": aliyun,
"aws": aws,
"azure": AzureUpload(),
}
log.Println("--Hello World")
return func(ctx *Context) (err error) {
log.Println("processing UploadFilter")
fmt.Printf("Name:%s\n", ctx.Req.Name)
var uploader Uploader
uploader, ok := uploaderMap[ctx.Req.Upload]
if !ok {
uploader = aliyun
}
if err = uploader.Upload(context.Background(), ctx.Req.Data); err != nil {
return
}
if err := ctx.Next(); err != nil {
return err
}
return nil
}
}
func main() {
d := NewFilterDecorator()
d.Use(ValidateParam())
d.Use(ProcessFilter())
d.Use(UploadFilter())
req := new(Request)
req.Data = "Hello World"
req.Upload = "azure"
resp := new(Response)
if err := d.Do(req, resp); err != nil {
log.Println(err)
}
}
网友评论