func(r *Request)ParseForm()error { var err error if r.PostForm == nil { if r.Method == "POST" || r.Method == "PUT" || r.Method == "PATCH" { r.PostForm, err = parsePostForm(r) // !!!!!!!!!!!!!! } if r.PostForm == nil { r.PostForm = make(url.Values) } } if r.Form == nil { iflen(r.PostForm) > 0 { r.Form = make(url.Values) copyValues(r.Form, r.PostForm) } var newValues url.Values if r.URL != nil { var e error newValues, e = url.ParseQuery(r.URL.RawQuery) if err == nil { err = e } } if newValues == nil { newValues = make(url.Values) } if r.Form == nil { r.Form = newValues } else { copyValues(r.Form, newValues) // !!!!!!!!!!!!!! } } return err }
funcparsePostForm(r *Request)(vs url.Values, err error) { if r.Body == nil { err = errors.New("missing form body") return } ct := r.Header.Get("Content-Type") // RFC 7231, section 3.1.1.5 - empty type // MAY be treated as application/octet-stream if ct == "" { ct = "application/octet-stream" } ct, _, err = mime.ParseMediaType(ct) switch { case ct == "application/x-www-form-urlencoded": // !!!!!!!!!!!!!! var reader io.Reader = r.Body maxFormSize := int64(1<<63 - 1) if _, ok := r.Body.(*maxBytesReader); !ok { maxFormSize = int64(10 << 20) // 10 MB is a lot of text. reader = io.LimitReader(r.Body, maxFormSize+1) } b, e := io.ReadAll(reader) if e != nil { if err == nil { err = e } break } ifint64(len(b)) > maxFormSize { err = errors.New("http: POST too large") return } vs, e = url.ParseQuery(string(b)) if err == nil { err = e } case ct == "multipart/form-data": // handled by ParseMultipartForm (which is calling us, or should be) // TODO(bradfitz): there are too many possible // orders to call too many functions here. // Clean this up and write more tests. // request_test.go contains the start of this, // in TestParseMultipartFormOrder and others. } return }
funccopyValues(dst, src url.Values) { for k, vs := range src { dst[k] = append(dst[k], vs...) // !!!!!!!!!!!!!! } }
funcparseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value)error { for i := 0; i < objT.NumField(); i++ { ...
// !!!!!!!!!!!!!! formValues := form[tag] var value string iflen(formValues) == 0 { defaultValue := fieldT.Tag.Get("default") if defaultValue != "" { value = defaultValue } else { continue } } iflen(formValues) == 1 { value = formValues[0] if value == "" { continue } }
... } returnnil }
我们的上传接口是 PUT 方法, 且 Content-Type: application/x-www-form-urlencoded