how to combine regular FormValue with multipart form data in Golang net/http Request

huangapple go评论77阅读模式
英文:

how to combine regular FormValue with multipart form data in Golang net/http Request

问题

我想在服务请求之前,从几个中间件处理函数中调用golang net/http Request上的FormValue方法。而且我不希望在执行此操作时使请求无效。

这个方法在除了当传入请求是multipart form-data时都能正常工作,但是在调用FormValue之后,数据会变得无效,最终路由中没有可解析的内容。

英文:

I want to call FormValue on golang net/http Request from several middleware handler functions before serving the request. And I do not want to invalidate the request while doing this.

It works fine except when the incoming request has a multipart form-data, the data gets invalidated after I call FormValue and there is nothing to parse in the final route.

答案1

得分: 4

我写了一个实用函数来解决我的问题:

package utils

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

// 在不使请求体无效的情况下获取表单值,以防数据是多部分的
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 { // 多部分表单
        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
    }
}

// 在不使请求体无效的情况下获取表单值
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...})
英文:

I wrote a utility function that solved my problem:

package utils
import (
&quot;bytes&quot;
&quot;io&quot;
&quot;io/ioutil&quot;
&quot;mime&quot;
&quot;mime/multipart&quot;
&quot;net/http&quot;
&quot;strings&quot;
)
// 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(&quot;Content-Type&quot;))
if err != nil || !strings.HasPrefix(mediaType, &quot;multipart/&quot;) {
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[&quot;boundary&quot;])
for len(values) &lt; 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 &quot;&quot;
}
}

Now instead of calling

value := request.FormValue(key)

I do

value := utils.GetFormValue(request, key)

or for multiple values

values := utils.GetFormValues(request, []string{keys...})

huangapple
  • 本文由 发表于 2016年11月17日 07:52:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/40644415.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定