2016-11-16 5 views
1

FormValuegolangnet/httpRequestに電話して、リクエストを処理する前にいくつかのミドルウェアハンドラ関数から呼び出したいとします。そして、私はこれをしながら要求を無効にしたくない。Golang net/httpリクエストで通常のFormValueとマルチパートフォームデータを結合する方法

着信要求がmultipartform-dataの場合を除いて正常に動作しますが、FormValueを呼び出した後にデータが無効になり、最終ルートで解析するものはありません。

+1

「データが無効になる」よりも具体的になりますか?どのようなエラーが表示されますか?後続の呼び出しは、 '' ''または何らかのパニックを返します...または? – BadZen

+1

ドキュメントから: "FormValueはParseMultipartFormとParseFormを必要に応じて呼び出します" ... "ParseMultipartFormを1回呼び出した後の呼び出しは効果がありません。" 'FormValue()'は本質的に反復可能ではないかもしれません(私のバグのように聞こえるでしょう!)。テストする簡単な例はありますか? – BadZen

+0

コンテンツはnilです。 – Jana

答えて

3

私は私の問題を解決するユーティリティ関数を書いた:

package utils 

import (
    "bytes" 
    "io" 
    "io/ioutil" 
    "mime" 
    "mime/multipart" 
    "net/http" 
    "strings" 
) 

// Get form values without invalidating the request body in case the data is multiform 
func GetFormValues(request *http.Request, keys []string) []string { 
    var values []string 
    mediaType, params, err := mime.ParseMediaType(request.Header.Get("Content-Type")) 
    if err != nil || !strings.HasPrefix(mediaType, "multipart/") { 
     for i := range keys { 
      values = append(values, request.FormValue(keys[i])) 
     } 
    } else { // multi form 
     buf, _ := ioutil.ReadAll(request.Body) 
     origBody := ioutil.NopCloser(bytes.NewBuffer(buf)) 
     var rdr = multipart.NewReader(bytes.NewBuffer(buf), params["boundary"]) 
     for len(values) < len(keys) { 
      part, err_part := rdr.NextPart() 
      if err_part == io.EOF { 
       break 
      } 
      for i := range keys { 
       if part.FormName() == keys[i] { 
        buf := new(bytes.Buffer) 
        buf.ReadFrom(part) 
        values = append(values, buf.String()) 
       } 
      } 
     } 
     request.Body = origBody 
    } 
    if len(values) == len(keys) { 
     return values 
    } else { 
     return nil 
    } 
} 

// Get form value without invalidating the request body in case the data is multiform 
func GetFormValue(request *http.Request, key string) string { 
    if result := GetFormValues(request, []string{key}); len(result) == 1 { 
     return result[0] 
    } else { 
     return "" 
    } 
} 

今の代わりに、

value := request.FormValue(key) 
を呼び出して、私は

value := utils.GetFormValue(request, key) 

または複数の値のために

values := utils.GetFormValues(request, []string{keys...}) 
を行います
+0

クール!これはhttps://github.com/golang/go/issuesのbug/rfeかもしれませんか? (現在の動作は、この使用例で/ segfault /を引き起こしていたバグを修正した結果であるように見えます) – BadZen

+0

これはバグでなければならないと私は同意します。リクエスト本体がnil FormValue関数を呼び出した後 – Jana

関連する問題