body-request.go 7.5 KB
Newer Older
E
eoLinker API Management 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
package common

import (
	"bytes"
	"errors"

	goku_plugin "github.com/eolinker/goku-plugin"

	"io/ioutil"
	"net/http"

	"mime"
	"mime/multipart"
	"net/url"
)

const defaultMultipartMemory = 32 << 20 // 32 MB
var (
Y
Your Name 已提交
19 20 21
	errNotForm      = errors.New("contentType is not Form")
	errNotMultipart = errors.New("contentType is not Multipart")
	errNotAllowRaw  = errors.New("contentType is not allow Raw")
E
eoLinker API Management 已提交
22 23
)

Y
Your Name 已提交
24
//BodyRequestHandler body request handler
E
eoLinker API Management 已提交
25 26 27 28 29 30 31 32 33 34 35
type BodyRequestHandler struct {
	form            url.Values
	rawbody         []byte
	orgContentParam map[string]string
	contentType     string
	files           map[string]*goku_plugin.FileHeader

	isInit     bool
	isWriteRaw bool
}

Y
Your Name 已提交
36
//Files files
E
eoLinker API Management 已提交
37 38 39 40 41 42 43 44 45 46
func (b *BodyRequestHandler) Files() (map[string]*goku_plugin.FileHeader, error) {

	err := b.Parse()

	if err != nil {
		return nil, err
	}
	return b.files, nil

}
Y
Your Name 已提交
47 48

//Parse parse
E
eoLinker API Management 已提交
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 109 110 111 112 113 114 115
func (b *BodyRequestHandler) Parse() error {

	if b.isInit {
		return nil
	}

	contentType, _, _ := mime.ParseMediaType(b.contentType)

	switch contentType {
	case goku_plugin.MultipartForm:
		{
			r, err := multipartReader(b.contentType, false, b.rawbody)
			if err != nil {
				return err
			}
			form, err := r.ReadForm(defaultMultipartMemory)
			if err != nil {
				return err
			}

			if b.form == nil {
				b.form = make(url.Values)
			}
			for k, v := range form.Value {
				b.form[k] = append(b.form[k], v...)
			}

			b.files = make(map[string]*goku_plugin.FileHeader)
			for k, fs := range form.File {

				if len(fs) > 0 {
					file, err := fs[0].Open()
					if err != nil {
						return err
					}
					fileData, err := ioutil.ReadAll(file)
					if err != nil {
						return err
					}

					b.files[k] = &goku_plugin.FileHeader{
						FileName: fs[0].Filename,
						Data:     fileData,
						Header:   fs[0].Header,
					}
				}
			}
		}
	case goku_plugin.FormData:
		{
			form, err := url.ParseQuery(string(b.rawbody))
			if err != nil {
				return err
			}
			if b.form == nil {
				b.form = form
			} else {
				for k, v := range form {
					b.form[k] = append(b.form[k], v...)
				}
			}

		}
	}
	b.isInit = true
	return nil
}
Y
Your Name 已提交
116 117

//GetForm get form
E
eoLinker API Management 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131
func (b *BodyRequestHandler) GetForm(key string) string {

	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
		return ""
	}
	b.Parse()

	if !b.isInit || b.form == nil {
		return ""
	}
	return b.form.Get(key)
}

Y
Your Name 已提交
132
//GetFile getFile
E
eoLinker API Management 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
func (b *BodyRequestHandler) GetFile(key string) (file *goku_plugin.FileHeader, has bool) {

	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
		return nil, false
	}

	err := b.Parse()
	if err != nil {
		return nil, false
	}

	if !b.isInit || b.files == nil {
		return nil, false
	}
	f, has := b.files[key]
	return f, has
}

Y
Your Name 已提交
152
//SetToForm setToForm
E
eoLinker API Management 已提交
153 154 155 156
func (b *BodyRequestHandler) SetToForm(key, value string) error {

	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
Y
Your Name 已提交
157
		return errNotForm
E
eoLinker API Management 已提交
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
	}

	err := b.Parse()
	if err != nil {
		return err
	}
	b.isWriteRaw = false

	if b.form == nil {
		b.form = make(url.Values)
	}
	b.form.Set(key, value)
	b.isWriteRaw = false

	return nil
}

Y
Your Name 已提交
175
//AddForm addForm
E
eoLinker API Management 已提交
176 177 178
func (b *BodyRequestHandler) AddForm(key, value string) error {
	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
Y
Your Name 已提交
179
		return errNotForm
E
eoLinker API Management 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193
	}
	err := b.Parse()
	if err != nil {
		return err
	}
	b.isWriteRaw = false

	if b.form == nil {
		b.form = make(url.Values)
	}
	b.form.Add(key, value)
	return nil
}

Y
Your Name 已提交
194
//AddFile 新建文件参数
E
eoLinker API Management 已提交
195 196 197 198
func (b *BodyRequestHandler) AddFile(key string, file *goku_plugin.FileHeader) error {

	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
Y
Your Name 已提交
199
		return errNotMultipart
E
eoLinker API Management 已提交
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
	}
	err := b.Parse()
	if err != nil {
		return err
	}
	b.isWriteRaw = false
	if file == nil && b.files != nil {
		delete(b.files, key)
		return nil
	}
	if b.files == nil {
		b.files = make(map[string]*goku_plugin.FileHeader)
	}
	b.files[key] = file

	return nil
}

Y
Your Name 已提交
218
//Clone 请求克隆
E
eoLinker API Management 已提交
219 220 221 222 223 224 225
func (b *BodyRequestHandler) Clone() *BodyRequestHandler {

	rawbody, _ := b.RawBody()

	return NewBodyRequestHandler(b.contentType, rawbody)

}
Y
Your Name 已提交
226 227

//ContentType contentType
E
eoLinker API Management 已提交
228 229 230 231
func (b *BodyRequestHandler) ContentType() string {
	return b.contentType
}

Y
Your Name 已提交
232
//BodyForm 获取body参数
E
eoLinker API Management 已提交
233 234 235 236 237 238 239 240 241
func (b *BodyRequestHandler) BodyForm() (url.Values, error) {

	err := b.Parse()
	if err != nil {
		return nil, err
	}
	return b.form, nil
}

Y
Your Name 已提交
242
//Encode encode
E
eoLinker API Management 已提交
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
func (b *BodyRequestHandler) Encode() error {
	if b.isWriteRaw {
		return nil

	}
	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
		b.isWriteRaw = true
		return nil
	}

	if len(b.files) > 0 {
		body := new(bytes.Buffer)
		writer := multipart.NewWriter(body)

		for fieldname, file := range b.files {
			part, err := writer.CreateFormFile(fieldname, file.FileName)
			if err != nil {
				return err
			}
			_, err = part.Write(file.Data)
			if err != nil {
				return err
			}
		}

		for fieldname, values := range b.form {
			temp := make(url.Values)
			temp[fieldname] = values
			value := temp.Encode()
			err := writer.WriteField(fieldname, value)
			if err != nil {
				return err
			}
		}
		err := writer.Close()
		if err != nil {
			return err
		}
		b.contentType = writer.FormDataContentType()
		b.rawbody = body.Bytes()
		b.isWriteRaw = true
	} else {
		if b.form != nil {
			b.rawbody = []byte(b.form.Encode())
		} else {
			b.rawbody = make([]byte, 0, 0)
		}
	}
	return nil
}

Y
Your Name 已提交
295
//RawBody rawBody
E
eoLinker API Management 已提交
296 297 298 299 300 301 302 303 304 305
func (b *BodyRequestHandler) RawBody() ([]byte, error) {

	err := b.Encode()
	if err != nil {
		return nil, err
	}
	return b.rawbody, nil

}

Y
Your Name 已提交
306
//SetForm 设置表单参数
E
eoLinker API Management 已提交
307 308 309 310
func (b *BodyRequestHandler) SetForm(values url.Values) error {

	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
Y
Your Name 已提交
311
		return errNotForm
E
eoLinker API Management 已提交
312 313 314 315 316 317 318 319
	}
	b.Parse()
	b.form = values
	b.isWriteRaw = false

	return nil
}

Y
Your Name 已提交
320
//SetFile 设置文件参数
E
eoLinker API Management 已提交
321 322 323 324
func (b *BodyRequestHandler) SetFile(files map[string]*goku_plugin.FileHeader) error {

	contentType, _, _ := mime.ParseMediaType(b.contentType)
	if contentType != goku_plugin.FormData && contentType != goku_plugin.MultipartForm {
Y
Your Name 已提交
325
		return errNotForm
E
eoLinker API Management 已提交
326 327 328 329 330 331 332 333 334
	}
	b.Parse()
	b.files = files
	// b.form = values
	b.isWriteRaw = false

	return nil
}

Y
Your Name 已提交
335
//SetRaw 设置Raw
E
eoLinker API Management 已提交
336 337 338 339 340 341 342 343
func (b *BodyRequestHandler) SetRaw(contentType string, body []byte) {

	b.rawbody, b.contentType, b.isInit, b.isWriteRaw = body, contentType, false, true
	_, b.orgContentParam, _ = mime.ParseMediaType(contentType)
	return

}

Y
Your Name 已提交
344
//NewBodyRequestHandler 创建body请求处理器
E
eoLinker API Management 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
func NewBodyRequestHandler(contentType string, body []byte) *BodyRequestHandler {
	b := new(BodyRequestHandler)
	b.SetRaw(contentType, body)
	return b
}

func multipartReader(contentType string, allowMixed bool, raw []byte) (*multipart.Reader, error) {

	if contentType == "" {
		return nil, http.ErrNotMultipart
	}
	d, params, err := mime.ParseMediaType(contentType)
	if err != nil || !(d == "multipart/form-data" || allowMixed && d == "multipart/mixed") {
		return nil, http.ErrNotMultipart
	}
	boundary, ok := params["boundary"]
	if !ok {
		return nil, http.ErrMissingBoundary
	}
	body := ioutil.NopCloser(bytes.NewBuffer(raw))
	return multipart.NewReader(body, boundary), nil
}