期望结果:
当我使用 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 ?但我折腾了太久,直到实在没有办法才发帖求助。
求大佬们指点,(拜谢
1
BlackBerry999 2020-01-14 17:24:05 +08:00
jsonData, err := json.Marshal(request_auth)
把这里的 jsonData 打印出来 fmt.Println(string(jsonData )) 看是否包含 [auth_user] |
2
Aumujun OP @BlackBerry999
```json {"auth_user":"admin","auth_pwd":"goodjob@123","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\"}"} ``` |
3
virusdefender 2020-01-14 17:34:40 +08:00
wireshark 抓包看下发出去的是啥样的
|
4
BlackBerry999 2020-01-14 17:35:02 +08:00
@Aumujun 我觉得是 json_data 内的字符串问题 二次 JSON 序列化 带上了很多\ 导致服务端对请求解析错误
|
5
Aumujun OP |
6
useben 2020-01-14 18:10:10 +08:00
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"` } 不需要二次序列化 |
7
index90 2020-01-14 18:17:12 +08:00
你的服务器接收的 post 请求,是 form data 格式的吧,不是 json 吧。
r = requests.post(HOST, data=json_data) |
8
kidtest 2020-01-14 18:19:43 +08:00
同意楼上,post 默认的 content-type 应该是"application/x-www-form-unlencoded"
|
9
index90 2020-01-14 18:20:31 +08:00
py 里,如果想发送 json 数据,正确的方法是:
``` r = requests .post(HOST, data=json_dump(json_data)) ``` 或者 ``` r = requests .post(HOST, json=json_data) ``` 既然你的 py 代码能正常工作,则表明服务端把你的 post 请求,以 formdata 格式处理 |
10
Vegetable 2020-01-14 18:20:49 +08:00
@index90 我猜是这样,requests 的 data 参数发出去是 form,a=b&c=d 样式的,不是 json,而你 golang 的代码是用 json 发出去的
用 url.Values 试试好了。 |