podman

Форк
0
485 строк · 12.1 Кб
1
// Copyright 2015 go-swagger maintainers
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package middleware
16

17
import (
18
	"encoding"
19
	"encoding/base64"
20
	"fmt"
21
	"io"
22
	"net/http"
23
	"reflect"
24
	"strconv"
25

26
	"github.com/go-openapi/errors"
27
	"github.com/go-openapi/spec"
28
	"github.com/go-openapi/strfmt"
29
	"github.com/go-openapi/swag"
30
	"github.com/go-openapi/validate"
31

32
	"github.com/go-openapi/runtime"
33
)
34

35
const defaultMaxMemory = 32 << 20
36

37
var textUnmarshalType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
38

39
func newUntypedParamBinder(param spec.Parameter, spec *spec.Swagger, formats strfmt.Registry) *untypedParamBinder {
40
	binder := new(untypedParamBinder)
41
	binder.Name = param.Name
42
	binder.parameter = &param
43
	binder.formats = formats
44
	if param.In != "body" {
45
		binder.validator = validate.NewParamValidator(&param, formats)
46
	} else {
47
		binder.validator = validate.NewSchemaValidator(param.Schema, spec, param.Name, formats)
48
	}
49

50
	return binder
51
}
52

53
type untypedParamBinder struct {
54
	parameter *spec.Parameter
55
	formats   strfmt.Registry
56
	Name      string
57
	validator validate.EntityValidator
58
}
59

60
func (p *untypedParamBinder) Type() reflect.Type {
61
	return p.typeForSchema(p.parameter.Type, p.parameter.Format, p.parameter.Items)
62
}
63

64
func (p *untypedParamBinder) typeForSchema(tpe, format string, items *spec.Items) reflect.Type {
65
	switch tpe {
66
	case "boolean":
67
		return reflect.TypeOf(true)
68

69
	case "string":
70
		if tt, ok := p.formats.GetType(format); ok {
71
			return tt
72
		}
73
		return reflect.TypeOf("")
74

75
	case "integer":
76
		switch format {
77
		case "int8":
78
			return reflect.TypeOf(int8(0))
79
		case "int16":
80
			return reflect.TypeOf(int16(0))
81
		case "int32":
82
			return reflect.TypeOf(int32(0))
83
		case "int64":
84
			return reflect.TypeOf(int64(0))
85
		default:
86
			return reflect.TypeOf(int64(0))
87
		}
88

89
	case "number":
90
		switch format {
91
		case "float":
92
			return reflect.TypeOf(float32(0))
93
		case "double":
94
			return reflect.TypeOf(float64(0))
95
		}
96

97
	case "array":
98
		if items == nil {
99
			return nil
100
		}
101
		itemsType := p.typeForSchema(items.Type, items.Format, items.Items)
102
		if itemsType == nil {
103
			return nil
104
		}
105
		return reflect.MakeSlice(reflect.SliceOf(itemsType), 0, 0).Type()
106

107
	case "file":
108
		return reflect.TypeOf(&runtime.File{}).Elem()
109

110
	case "object":
111
		return reflect.TypeOf(map[string]interface{}{})
112
	}
113
	return nil
114
}
115

116
func (p *untypedParamBinder) allowsMulti() bool {
117
	return p.parameter.In == "query" || p.parameter.In == "formData"
118
}
119

120
func (p *untypedParamBinder) readValue(values runtime.Gettable, target reflect.Value) ([]string, bool, bool, error) {
121
	name, in, cf, tpe := p.parameter.Name, p.parameter.In, p.parameter.CollectionFormat, p.parameter.Type
122
	if tpe == "array" {
123
		if cf == "multi" {
124
			if !p.allowsMulti() {
125
				return nil, false, false, errors.InvalidCollectionFormat(name, in, cf)
126
			}
127
			vv, hasKey, _ := values.GetOK(name)
128
			return vv, false, hasKey, nil
129
		}
130

131
		v, hk, hv := values.GetOK(name)
132
		if !hv {
133
			return nil, false, hk, nil
134
		}
135
		d, c, e := p.readFormattedSliceFieldValue(v[len(v)-1], target)
136
		return d, c, hk, e
137
	}
138

139
	vv, hk, _ := values.GetOK(name)
140
	return vv, false, hk, nil
141
}
142

143
func (p *untypedParamBinder) Bind(request *http.Request, routeParams RouteParams, consumer runtime.Consumer, target reflect.Value) error {
144
	// fmt.Println("binding", p.name, "as", p.Type())
145
	switch p.parameter.In {
146
	case "query":
147
		data, custom, hasKey, err := p.readValue(runtime.Values(request.URL.Query()), target)
148
		if err != nil {
149
			return err
150
		}
151
		if custom {
152
			return nil
153
		}
154

155
		return p.bindValue(data, hasKey, target)
156

157
	case "header":
158
		data, custom, hasKey, err := p.readValue(runtime.Values(request.Header), target)
159
		if err != nil {
160
			return err
161
		}
162
		if custom {
163
			return nil
164
		}
165
		return p.bindValue(data, hasKey, target)
166

167
	case "path":
168
		data, custom, hasKey, err := p.readValue(routeParams, target)
169
		if err != nil {
170
			return err
171
		}
172
		if custom {
173
			return nil
174
		}
175
		return p.bindValue(data, hasKey, target)
176

177
	case "formData":
178
		var err error
179
		var mt string
180

181
		mt, _, e := runtime.ContentType(request.Header)
182
		if e != nil {
183
			// because of the interface conversion go thinks the error is not nil
184
			// so we first check for nil and then set the err var if it's not nil
185
			err = e
186
		}
187

188
		if err != nil {
189
			return errors.InvalidContentType("", []string{"multipart/form-data", "application/x-www-form-urlencoded"})
190
		}
191

192
		if mt != "multipart/form-data" && mt != "application/x-www-form-urlencoded" {
193
			return errors.InvalidContentType(mt, []string{"multipart/form-data", "application/x-www-form-urlencoded"})
194
		}
195

196
		if mt == "multipart/form-data" {
197
			if err = request.ParseMultipartForm(defaultMaxMemory); err != nil {
198
				return errors.NewParseError(p.Name, p.parameter.In, "", err)
199
			}
200
		}
201

202
		if err = request.ParseForm(); err != nil {
203
			return errors.NewParseError(p.Name, p.parameter.In, "", err)
204
		}
205

206
		if p.parameter.Type == "file" {
207
			file, header, ffErr := request.FormFile(p.parameter.Name)
208
			if ffErr != nil {
209
				if p.parameter.Required {
210
					return errors.NewParseError(p.Name, p.parameter.In, "", ffErr)
211
				} else {
212
					return nil
213
				}
214
			}
215
			target.Set(reflect.ValueOf(runtime.File{Data: file, Header: header}))
216
			return nil
217
		}
218

219
		if request.MultipartForm != nil {
220
			data, custom, hasKey, rvErr := p.readValue(runtime.Values(request.MultipartForm.Value), target)
221
			if rvErr != nil {
222
				return rvErr
223
			}
224
			if custom {
225
				return nil
226
			}
227
			return p.bindValue(data, hasKey, target)
228
		}
229
		data, custom, hasKey, err := p.readValue(runtime.Values(request.PostForm), target)
230
		if err != nil {
231
			return err
232
		}
233
		if custom {
234
			return nil
235
		}
236
		return p.bindValue(data, hasKey, target)
237

238
	case "body":
239
		newValue := reflect.New(target.Type())
240
		if !runtime.HasBody(request) {
241
			if p.parameter.Default != nil {
242
				target.Set(reflect.ValueOf(p.parameter.Default))
243
			}
244

245
			return nil
246
		}
247
		if err := consumer.Consume(request.Body, newValue.Interface()); err != nil {
248
			if err == io.EOF && p.parameter.Default != nil {
249
				target.Set(reflect.ValueOf(p.parameter.Default))
250
				return nil
251
			}
252
			tpe := p.parameter.Type
253
			if p.parameter.Format != "" {
254
				tpe = p.parameter.Format
255
			}
256
			return errors.InvalidType(p.Name, p.parameter.In, tpe, nil)
257
		}
258
		target.Set(reflect.Indirect(newValue))
259
		return nil
260
	default:
261
		return errors.New(500, fmt.Sprintf("invalid parameter location %q", p.parameter.In))
262
	}
263
}
264

265
func (p *untypedParamBinder) bindValue(data []string, hasKey bool, target reflect.Value) error {
266
	if p.parameter.Type == "array" {
267
		return p.setSliceFieldValue(target, p.parameter.Default, data, hasKey)
268
	}
269
	var d string
270
	if len(data) > 0 {
271
		d = data[len(data)-1]
272
	}
273
	return p.setFieldValue(target, p.parameter.Default, d, hasKey)
274
}
275

276
func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string, hasKey bool) error {
277
	tpe := p.parameter.Type
278
	if p.parameter.Format != "" {
279
		tpe = p.parameter.Format
280
	}
281

282
	if (!hasKey || (!p.parameter.AllowEmptyValue && data == "")) && p.parameter.Required && p.parameter.Default == nil {
283
		return errors.Required(p.Name, p.parameter.In, data)
284
	}
285

286
	ok, err := p.tryUnmarshaler(target, defaultValue, data)
287
	if err != nil {
288
		return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
289
	}
290
	if ok {
291
		return nil
292
	}
293

294
	defVal := reflect.Zero(target.Type())
295
	if defaultValue != nil {
296
		defVal = reflect.ValueOf(defaultValue)
297
	}
298

299
	if tpe == "byte" {
300
		if data == "" {
301
			if target.CanSet() {
302
				target.SetBytes(defVal.Bytes())
303
			}
304
			return nil
305
		}
306

307
		b, err := base64.StdEncoding.DecodeString(data)
308
		if err != nil {
309
			b, err = base64.URLEncoding.DecodeString(data)
310
			if err != nil {
311
				return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
312
			}
313
		}
314
		if target.CanSet() {
315
			target.SetBytes(b)
316
		}
317
		return nil
318
	}
319

320
	switch target.Kind() {
321
	case reflect.Bool:
322
		if data == "" {
323
			if target.CanSet() {
324
				target.SetBool(defVal.Bool())
325
			}
326
			return nil
327
		}
328
		b, err := swag.ConvertBool(data)
329
		if err != nil {
330
			return err
331
		}
332
		if target.CanSet() {
333
			target.SetBool(b)
334
		}
335
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
336
		if data == "" {
337
			if target.CanSet() {
338
				rd := defVal.Convert(reflect.TypeOf(int64(0)))
339
				target.SetInt(rd.Int())
340
			}
341
			return nil
342
		}
343
		i, err := strconv.ParseInt(data, 10, 64)
344
		if err != nil {
345
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
346
		}
347
		if target.OverflowInt(i) {
348
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
349
		}
350
		if target.CanSet() {
351
			target.SetInt(i)
352
		}
353

354
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
355
		if data == "" {
356
			if target.CanSet() {
357
				rd := defVal.Convert(reflect.TypeOf(uint64(0)))
358
				target.SetUint(rd.Uint())
359
			}
360
			return nil
361
		}
362
		u, err := strconv.ParseUint(data, 10, 64)
363
		if err != nil {
364
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
365
		}
366
		if target.OverflowUint(u) {
367
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
368
		}
369
		if target.CanSet() {
370
			target.SetUint(u)
371
		}
372

373
	case reflect.Float32, reflect.Float64:
374
		if data == "" {
375
			if target.CanSet() {
376
				rd := defVal.Convert(reflect.TypeOf(float64(0)))
377
				target.SetFloat(rd.Float())
378
			}
379
			return nil
380
		}
381
		f, err := strconv.ParseFloat(data, 64)
382
		if err != nil {
383
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
384
		}
385
		if target.OverflowFloat(f) {
386
			return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
387
		}
388
		if target.CanSet() {
389
			target.SetFloat(f)
390
		}
391

392
	case reflect.String:
393
		value := data
394
		if value == "" {
395
			value = defVal.String()
396
		}
397
		// validate string
398
		if target.CanSet() {
399
			target.SetString(value)
400
		}
401

402
	case reflect.Ptr:
403
		if data == "" && defVal.Kind() == reflect.Ptr {
404
			if target.CanSet() {
405
				target.Set(defVal)
406
			}
407
			return nil
408
		}
409
		newVal := reflect.New(target.Type().Elem())
410
		if err := p.setFieldValue(reflect.Indirect(newVal), defVal, data, hasKey); err != nil {
411
			return err
412
		}
413
		if target.CanSet() {
414
			target.Set(newVal)
415
		}
416

417
	default:
418
		return errors.InvalidType(p.Name, p.parameter.In, tpe, data)
419
	}
420
	return nil
421
}
422

423
func (p *untypedParamBinder) tryUnmarshaler(target reflect.Value, defaultValue interface{}, data string) (bool, error) {
424
	if !target.CanSet() {
425
		return false, nil
426
	}
427
	// When a type implements encoding.TextUnmarshaler we'll use that instead of reflecting some more
428
	if reflect.PtrTo(target.Type()).Implements(textUnmarshalType) {
429
		if defaultValue != nil && len(data) == 0 {
430
			target.Set(reflect.ValueOf(defaultValue))
431
			return true, nil
432
		}
433
		value := reflect.New(target.Type())
434
		if err := value.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(data)); err != nil {
435
			return true, err
436
		}
437
		target.Set(reflect.Indirect(value))
438
		return true, nil
439
	}
440
	return false, nil
441
}
442

443
func (p *untypedParamBinder) readFormattedSliceFieldValue(data string, target reflect.Value) ([]string, bool, error) {
444
	ok, err := p.tryUnmarshaler(target, p.parameter.Default, data)
445
	if err != nil {
446
		return nil, true, err
447
	}
448
	if ok {
449
		return nil, true, nil
450
	}
451

452
	return swag.SplitByFormat(data, p.parameter.CollectionFormat), false, nil
453
}
454

455
func (p *untypedParamBinder) setSliceFieldValue(target reflect.Value, defaultValue interface{}, data []string, hasKey bool) error {
456
	sz := len(data)
457
	if (!hasKey || (!p.parameter.AllowEmptyValue && (sz == 0 || (sz == 1 && data[0] == "")))) && p.parameter.Required && defaultValue == nil {
458
		return errors.Required(p.Name, p.parameter.In, data)
459
	}
460

461
	defVal := reflect.Zero(target.Type())
462
	if defaultValue != nil {
463
		defVal = reflect.ValueOf(defaultValue)
464
	}
465

466
	if !target.CanSet() {
467
		return nil
468
	}
469
	if sz == 0 {
470
		target.Set(defVal)
471
		return nil
472
	}
473

474
	value := reflect.MakeSlice(reflect.SliceOf(target.Type().Elem()), sz, sz)
475

476
	for i := 0; i < sz; i++ {
477
		if err := p.setFieldValue(value.Index(i), nil, data[i], hasKey); err != nil {
478
			return err
479
		}
480
	}
481

482
	target.Set(value)
483

484
	return nil
485
}
486

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.