我是 Golang 新手,有 Python 背景,在管理表单请求时遇到一些问题。
我正在尝试使用 Go 以表单格式发送数据,以模仿此curl 调用:
curl -X POST -k --cacert mycert --key mykey --cert cert "https://api/v1/house?action=paint&room=hall" -F "houses=street123"
这是我在 API 服务器(在 Flask 上运行)中看到的内容,它通过curl 检查请求中的 header 和表单信息进行调用。
标题
Host: localhost
Connection: close
Content-Length: 152
User-Agent: curl/7.29.0
Accept: */*
Content-Type: multipart/form-data; boundary=----------------------------991133af3afb
表格
ImmutableMultiDict([('houses', 'street123')])
当我使用 GO 代码执行此操作时,我得到以下信息:
标题
Host: localhost
Connection: close
Content-Length: 18
User-Agent: Go-http-client/1.1
Accept-Encoding: */*
Content-Type: multipart/form-data
表格
ImmutableMultiDict([])
我在做什么:
1-我正在 Generate_client
中生成一个客户端,用于通过相互 tls 进行身份验证
2- 我使用 map[string][]string
作为负载来调用 API,并在调用之前打印它以确保它已正确构造。
- 我在调用函数时返回正文并打印它。
这是我的结果:
Doing Form call
Params after maping:map[houses:[street123]]
FULL-URL:https://api/v1/house?action=paint&room=hall
Params encoded:&{houses=street123 0 -1}
这是我的代码
func Generate_client() *http.Client {
caCert, err := ioutil.ReadFile(cacert)
checkForErrors(err)
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// Create key pair for certificate
cert, err := tls.LoadX509KeyPair(cert, key)
checkForErrors(err)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
Certificates: []tls.Certificate{cert},
},
},
}
return client
}
func CallFormUrl(endpoint string, method string, dataPayload []string) string {
fmt.Println("Doing Form call")
FormMap := ConvertPayloadToMap(dataPayload)
params := url.Values{}
for key, value:= range FormMap{
params.Add(key,value)
}
fmt.Println("Params after maping:"+params)
client := Generate_client()
fullUrl := controllerUrl+endpoint
fmt.Println("FULL-URL:"+fullUrl)
var ContentType string = "multipart/form-data"
var err error
var req *http.Request
fmt.Println("Params encoded:"+strings.NewReader(params.Encode()))
switch method {
case "POST":
req, err = http.NewRequest(http.MethodPost, fullUrl, strings.NewReader(params.Encode()))
case "PUT":
req, err = http.NewRequest(http.MethodPut, fullUrl, strings.NewReader(params.Encode()))
case "GET":
req, err = http.NewRequest(http.MethodGet, fullUrl, strings.NewReader(params.Encode()))
case "DELETE":
req, err = http.NewRequest(http.MethodDelete, fullUrl, strings.NewReader(params.Encode()))
}
req.Header.Set("Content-type", ContentType)
checkForErrors(err)
resp, err:= client.Do(req)
checkForErrors(err)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
return string(body)
}
为什么表单数据没有发送出去?
最佳答案
构建多部分请求比构建普通的 urlencoded 表单更为冗长,因此如果您需要在很多地方使用多部分,您可能希望将其抽象为一个函数,以便让您的生活更轻松。
这是一个例子:
params := url.Values{"houses": {"street123"}}
buf := bytes.Buffer{}
w := multipart.NewWriter(&buf)
ct := w.FormDataContentType()
h := make(textproto.MIMEHeader)
h.Set("Content-Type", "application/x-www-form-urlencoded")
if pw, err := w.CreatePart(h); err != nil {
panic(err)
} else if _, err := pw.Write([]byte(params.Encode())); err != nil {
panic(err)
} else if err := w.Close(); err != nil {
panic(err)
}
r, err := http.NewRequest("POST", "https://example.com", &buf)
if err != nil {
panic(err)
}
r.Header.Set("Content-Type", ct)
re, err := client.Do(r)
// ...
关于forms - 没有获取使用 go 发送的表单数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62554131/