/
form.go
108 lines (86 loc) · 2.66 KB
/
form.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package httpio
import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/url"
)
var (
//MediaTypeForm identifies form content
MediaTypeForm = "application/x-www-form-urlencoded"
)
//FormDecodeProvider can be implemented to provide decoding of form maps into structs
//Incidentally, this interface is implemented immediately by `github.com/gorilla/schema`
type FormDecodeProvider interface {
Decode(dst interface{}, src map[string][]string) error
}
//FormEncodeProvider can be implemented to provide encoding of form maps from structs
//Incidentally, this interface is implemented immediately by `github.com/gorilla/schema`
type FormEncodeProvider interface {
Encode(src interface{}, dst map[string][]string) error
}
//FormEncoder uses the form encoding provider to implement the Encoding interface
type FormEncoder struct {
enc FormEncodeProvider
w io.Writer
}
//Encode the value v into the encoder writer
func (e *FormEncoder) Encode(v interface{}) error {
if e.enc == nil {
return errors.New("no form encoder configured")
}
vals := url.Values{}
err := e.enc.Encode(v, vals)
if err != nil {
return err
}
_, err = fmt.Fprintf(e.w, vals.Encode())
return err
}
//FormDecoder uses the form encoding provider to implement the Encoding interface
type FormDecoder struct {
dec FormDecodeProvider
r io.Reader
}
//Decode into v from the reader
func (e *FormDecoder) Decode(v interface{}) error {
if e.dec == nil {
return errors.New("no form decoder configured")
}
data, err := ioutil.ReadAll(e.r)
if err != nil {
return err
}
vals, err := url.ParseQuery(string(data))
if err != nil {
return err
}
err = e.dec.Decode(v, vals)
if err != nil {
return fmt.Errorf("failed to decode into %v from %v: %v", v, vals, err)
}
return err
}
type formEncoderFactory struct {
enc FormEncodeProvider
}
//MimeType will report the EncodingMimeType
func (e *formEncoderFactory) MimeType() string { return MediaTypeForm }
//Encoder will create encoders
func (e *formEncoderFactory) Encoder(w io.Writer) Encoder { return &FormEncoder{e.enc, w} }
type formDecoderFactory struct {
dec FormDecodeProvider
}
//MimeType will report the EncodingMimeType
func (e *formDecoderFactory) MimeType() string { return MediaTypeForm }
//Decoder will create decoders
func (e *formDecoderFactory) Decoder(r io.Reader) Decoder { return &FormDecoder{e.dec, r} }
//NewFormEncoding creates the factory using a provider, often third party library
func NewFormEncoding(p FormEncodeProvider) EncoderFactory {
return &formEncoderFactory{p}
}
//NewFormDecoding creates the factory using a provider, often third party library
func NewFormDecoding(p FormDecodeProvider) DecoderFactory {
return &formDecoderFactory{p}
}