/
plug.go
70 lines (58 loc) · 1.5 KB
/
plug.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package mapstruct
import (
"encoding/json"
"errors"
"net/http"
"strings"
"github.com/AlexanderChen1989/xrest"
"github.com/AlexanderChen1989/xrest/plugs"
"github.com/mitchellh/mapstructure"
"golang.org/x/net/context"
)
// New create new plugger
func New(onError plugs.OnErrorFn) xrest.Plugger {
p := &plug{
onError: onError,
}
if p.onError == nil {
p.onError = plugs.DefaultOnErrorFn
}
return p
}
type plug struct {
next xrest.Handler
onError plugs.OnErrorFn
}
var ctxKey uint8
func (p *plug) Plug(h xrest.Handler) xrest.Handler {
p.next = h
return p
}
const (
jsonMediaType = "application/json"
)
func (p *plug) ServeHTTP(ctx context.Context, w http.ResponseWriter, r *http.Request) {
mediaType := r.Header.Get("Content-Type")
if r.Method == "GET" || r.Method == "HEAD" || (len(mediaType) > 0 && !strings.HasPrefix(mediaType, jsonMediaType)) {
bp.next.ServeHTTP(ctx, w, r)
return
}
payload := map[string]interface{}{}
err := json.NewDecoder(r.Body).Decode(&payload)
if err != nil && p.onError != nil {
p.onError(ctx, w, r, err)
return
}
p.next.ServeHTTP(context.WithValue(ctx, &ctxKey, payload), w, r)
}
// ErrPlugNotPlugged mapstruct plug is not plugged to pipeline
var ErrPlugNotPlugged = errors.New("mapstruct plug is not plugged to pipeline")
// Decode payload to struct
func Decode(ctx context.Context, val interface{}) error {
payload, ok := ctx.Value(&ctxKey).(map[string]interface{})
if !ok {
return ErrPlugNotPlugged
}
mapstructure.Decode(payload, val)
return nil
}