求助,Golang Go语言中 http post 请求问题

发布于 1周前 作者 eggper 来自 Go语言

求助,Golang Go语言中 http post 请求问题

期望结果:

  • 正确获取 itop rest api 返回的工单数据

当我使用 Python 的 requests 库时,这一切都很正常,获取数据成功(如果我覆盖默认 headers,获取的结果如 golang 版本的一样。

这是 Python 的代码:

#!/usr/bin/python3
import requests, json

HOST = “http://192.168.17.22:8096/itop/webservices/rest.php?version=1.3

json_str = json.dumps({ “operation”: “core/get”, “class”: “UserRequest”, “key”: “SELECT UserRequest WHERE operational_status = ‘ongoing’”, “output_fields”: “request_type,servicesubcategory_name,urgency,origin,caller_id_friendlyname,impact,title,description”, }) json_data = { “auth_user”: “admin”, “auth_pwd”: “goodjob@123”, “json_data”: json_str }

secure_rest_services

def get(): r = requests.post(HOST, data=json_data) return r

if name == “main”: result = get() print(result.json())

输出

{'objects': {'UserRequest::7': {'code': 0, 'message': '', 'class': 'UserRequest', 'key': '7', 'fields': {'request_type': 'service_request', 'servicesubcategory_name': '钉钉权限开通', 'urgency': '4', 'origin': 'portal', 'caller_id_friendlyname': 'x 阿里合作项目负责人', 'impact': '1', 'title': '溫江|A-222|wb-xxxxxxxx', 'description': '<p>this is a test approve...</p>'}}, 'UserRequest::6': {'code': 0, 'message': '', 'class': 'UserRequest', 'key': '6', 'fields': {'request_type': 'service_request', 'servicesubcategory_name': '钉钉权限开通', 'urgency': '3', 'origin': 'portal', 'caller_id_friendlyname': 'x 阿里合作项目负责人', 'impact': '1', 'title': '成都|Xa-111|wb-xx111111', 'description': '<p>這是一個測試用的用戶需求</p>'}}}, 'code': 0, 'message': 'Found: 2'}

下面时 golang 版本的 post 请求

主函数:

package main

import ( “bytes” “encoding/json” “fmt” “io/ioutil” “log” “net/http” “strconv” )

// 釘釘應用程序的 agentid const ( ITOP_URL = http://192.168.17.22:8096/itop/webservices/rest.php?version=1.3 )

func main() { request_auth := new(RequestAuth) request_data := new(RequestData) request_auth.AuthUser = “admin” request_auth.AuthPwd = “goodjob@123

request_data.Operation = "core/get"
request_data.Class = "UserRequest"
request_data.Key = "SELECT UserRequest WHERE operational_status = \"ongoing\""
request_data.OutPutFields = "request_type,servicesubcategory_name,urgency,origin,caller_id_friendlyname,impact,title,description"
req_data, err := json.Marshal(request_data)
if err != nil {
	panic(err)
}
request_auth.JsonData = string(req_data)

jsonData, err := json.Marshal(request_auth)
if err != nil {
	panic(err)
}
reader := bytes.NewReader(jsonData)
result := Post(ITOP_URL, reader)
fmt.Println(string(result))

}

func Post(url string, reader *bytes.Reader) []byte { request, err := http.NewRequest(“POST”, url, reader) if err != nil { panic(err) } request.Header.Set(“Content-Type”, “application/json”) request.Header.Set(“Content-Length”, strconv.Itoa(reader.Len())) client := http.Client{} resp, err := client.Do(request) if err != nil { log.Fatal(err.Error()) } defer resp.Body.Close() respBytes, _ := ioutil.ReadAll(resp.Body) return respBytes }

post 携带的数据模型

package main

// UserRequest structure type Base struct { Code int json:"code" Message string json:"message" }

type Fileds struct { RequestType string json:"request_type" ServiceSubcategoryName string json:"servicesubcategory_name" Urgency string json:"urgency" Origin string json:"origin" CallerIdFriendlyName string json:"caller_id_friendlyname" Impact string json:"impact" Title string json:"title" Description string json:"description" }

type ResponseContent struct { Code int json:"code" Message string json:"message" Class string json:"class" Key string json:"key" Filed Fileds json:"fields" }

type Response struct { Base Object map[string]ResponseContent json:"objects" }

// Request api data struct type RequestData struct { Operation string json:"operation" Class string json:"class" Key string json:"key" OutPutFields string json:"output_fields" }

type RequestAuth struct { AuthUser string json:"auth_user" AuthPwd string json:"auth_pwd" // JsonData RequestData json:"json_data" JsonData string json:"json_data" }

输出:

{"code":5,"message":"Error: Missing parameter 'auth_user'"}

我猜这应该是 itop 需要 post 请求携带某个 header ?但我折腾了太久,直到实在没有办法才发帖求助。

求大佬们指点,(拜谢


更多关于求助,Golang Go语言中 http post 请求问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

13 回复

jsonData, err := json.Marshal(request_auth)
把这里的 jsonData 打印出来 fmt.Println(string(jsonData )) 看是否包含 [auth_user]

更多关于求助,Golang Go语言中 http post 请求问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html




json<br>{"auth_user":"admin","auth_pwd":"goodjob123","json_data":"{\"operation\":\"core/get\",\"class\":\"UserRequest\",\"key\":\"SELECT UserRequest WHERE operational_status = \\\"ongoing\\\"\",\"output_fields\":\"request_type,servicesubcategory_name,urgency,origin,caller_id_friendlyname,impact,title,description\"}"}<br>

wireshark 抓包看下发出去的是啥样的

我觉得是 json_data 内的字符串问题 二次 JSON 序列化 带上了很多\ 导致服务端对请求解析错误

hi,刚刚我抓包了一下,发送的值和 2 楼我发的一模一样,有可能像四楼说的那样。

如果是这样有什么推荐的解法吗

type RequestData struct {
Operation string json:"operation"
Class string json:"class"
Key string json:"key"
OutPutFields string json:"output_fields"
}

type RequestAuth struct {
AuthUser string json:"auth_user"
AuthPwd string json:"auth_pwd"
// JsonData RequestData json:"json_data"
JsonData RequestData json:"json_data"
}

不需要二次序列化

你的服务器接收的 post 请求,是 form data 格式的吧,不是 json 吧。
r = requests.post(HOST, data=json_data)

同意楼上,post 默认的 content-type 应该是"application/x-www-form-unlencoded"

py 里,如果想发送 json 数据,正确的方法是:
<br>r = requests .post(HOST, data=json_dump(json_data))<br>
或者
<br>r = requests .post(HOST, json=json_data)<br>
既然你的 py 代码能正常工作,则表明服务端把你的 post 请求,以 formdata 格式处理

我猜是这样,requests 的 data 参数发出去是 form,a=b&c=d 样式的,不是 json,而你 golang 的代码是用 json 发出去的
用 url.Values 试试好了。


所以,应该使用 url.Values 去存你的那些数据,然后将 Encode 之后的数据当做 body,post 出去。
具体可以搜索:golang post form urlencoded





感谢几位的回复,解决了困扰我一天的难题,非常感谢。

你好!

关于你在 Golang 中遇到的 HTTP POST 请求问题,以下是一些可能的解决步骤和建议:

  1. 检查请求 URL 和端口: 确保你发送 POST 请求的 URL 和端口是正确的。如果 URL 有误或端口未开放,会导致请求失败。

  2. 设置请求头: POST 请求通常需要设置正确的 Content-Type 请求头。例如,如果你发送 JSON 数据,应该设置 Content-Type: application/json

  3. 构建请求体: 根据 Content-Type,确保请求体的格式正确。对于 JSON 数据,可以使用 json.Marshal 方法将结构体或 map 转换为 JSON 格式的字节数组。

  4. 处理响应: 发送请求后,要检查响应的状态码和响应体。如果状态码不是 2xx,说明请求未成功,可以根据响应体中的错误信息进一步调试。

  5. 错误处理: 在发送请求和处理响应的过程中,加入适当的错误处理逻辑,以便在出现问题时能够捕获并处理错误。

  6. 使用工具调试: 使用 Postman 或 curl 等工具测试相同的 POST 请求,看是否能成功。这有助于确定问题是出在 Go 代码上,还是服务器端的问题。

如果以上步骤仍未解决问题,请提供更详细的错误信息(如完整的错误日志和代码片段),以便进一步分析。希望这些信息对你有所帮助!

回到顶部