ScanParameters scans the request using the given path parameter objects in case an error is encountered a 400 along with a jsonapi errors object is sent to the ResponseWriter and false is returned. Returns true if all values were scanned successfully. The used scanning function is fmt.Sscan
(w http.ResponseWriter, r *http.Request, parameters ...*ScanParameter)
| 55 | // is sent to the ResponseWriter and false is returned. Returns true if all |
| 56 | // values were scanned successfully. The used scanning function is fmt.Sscan |
| 57 | func ScanParameters(w http.ResponseWriter, r *http.Request, parameters ...*ScanParameter) bool { |
| 58 | for _, param := range parameters { |
| 59 | var scanData string |
| 60 | |
| 61 | switch param.Location { |
| 62 | case ScanInPath: |
| 63 | // input is filled with path data |
| 64 | scanData = param.Input |
| 65 | case ScanInQuery: |
| 66 | // input may not be filled and needs to be parsed from the request |
| 67 | input := r.URL.Query()[param.Name] |
| 68 | |
| 69 | // if parameter is a slice |
| 70 | reValue := reflect.ValueOf(param.Data).Elem() |
| 71 | if reValue.Kind() == reflect.Slice { |
| 72 | size := len(input) |
| 73 | array := reflect.MakeSlice(reValue.Type(), size, size) |
| 74 | invalid := 0 |
| 75 | for i := 0; i < size; i++ { |
| 76 | if input[i] == "" { |
| 77 | invalid++ |
| 78 | continue |
| 79 | } |
| 80 | |
| 81 | arrElem := array.Index(i - invalid) |
| 82 | n, _ := Scan(input[i], arrElem.Addr().Interface()) // nolint: gosec |
| 83 | if n != 1 { |
| 84 | WriteError(w, http.StatusBadRequest, param.BuildInvalidValueError(arrElem.Type(), input[i])) |
| 85 | return false |
| 86 | } |
| 87 | } |
| 88 | // some of the query parameters where empty, filter them out |
| 89 | if invalid > 0 { |
| 90 | array = array.Slice(0, size-invalid) |
| 91 | } |
| 92 | reValue.Set(array) |
| 93 | |
| 94 | // skip parsing at the bottom of the loop |
| 95 | continue |
| 96 | } |
| 97 | |
| 98 | // single parameter scanning |
| 99 | scanData = strings.Join(input, " ") |
| 100 | case ScanInHeader: |
| 101 | scanData = r.Header.Get(param.Name) |
| 102 | default: |
| 103 | panic(fmt.Errorf("impossible scanning location: %d", param.Location)) |
| 104 | } |
| 105 | |
| 106 | n, _ := Scan(scanData, param.Data) |
| 107 | // only report on non empty data, govalidator will handle the other cases |
| 108 | if n != 1 && scanData != "" { |
| 109 | WriteError(w, http.StatusBadRequest, param.BuildInvalidValueError(reflect.ValueOf(param.Data).Type(), scanData)) |
| 110 | return false |
| 111 | } |
| 112 | } |
| 113 | return true |
| 114 | } |
searching dependent graphs…