英文:
POST golang request with string data
问题
我可以使用POSTMAN Chrome扩展程序进行字符串数据的POST请求。
我需要使用golang
代码完成相同的操作。
但是我的Go
代码丢失了字符串INSERT INTO V SET name = 'jack', boss = #11:19
,并且将空数据发送到服务器。
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
)
func main() {
client := &http.Client{}
// 为什么这个stringData丢失了,并且没有随POST请求发送?
stringData := `INSERT INTO V SET name = 'jack', boss = #11:19`
req, err := http.NewRequest("POST", "http://localhost:2480/command/GratefulDeadConcerts/sql", bytes.NewBufferString(stringData))
req.SetBasicAuth("root", "1")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error : %s", err)
}
fmt.Println("resp")
fmt.Println(ToJson(resp))
var b bytes.Buffer
_, err = b.ReadFrom(resp.Body)
if err != nil {
log.Fatal("Error : %s", err)
}
fmt.Println(b.String())
}
func ToJson(obj interface{}) string {
b, err := json.MarshalIndent(&obj, "", " ")
if err != nil {
fmt.Printf("Error : %s", err)
}
strJson := string(b)
return strJson
}
它的输出是:
resp
{
"Status": "500 Internal Server Error",
"StatusCode": 500,
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Cache-Control": [
"no-cache, no-store, max-age=0, must-revalidate"
],
"Connection": [
"Keep-Alive"
],
"Content-Length": [
"55"
],
"Content-Type": [
"text/plain; charset=utf-8"
],
"Date": [
"Mon Jun 08 10:47:46 MSK 2015"
],
"Pragma": [
"no-cache"
],
"Server": [
"OrientDB Server v.2.0.10 (build UNKNOWN@r; 2015-05-25 16:48:43+0000)"
]
},
"Body": {},
"ContentLength": 55,
"TransferEncoding": null,
"Close": false,
"Trailer": null,
"Request": {
"Method": "POST",
"URL": {
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "localhost:2480",
"Path": "/command/GratefulDeadConcerts/sql",
"RawQuery": "",
"Fragment": ""
},
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Authorization": [
"Basic cm9vdDox"
]
},
"Body": {
"Reader": {}
},
"ContentLength": 46,
"TransferEncoding": null,
"Close": false,
"Host": "localhost:2480",
"Form": null,
"PostForm": null,
"MultipartForm": null,
"Trailer": null,
"RemoteAddr": "",
"RequestURI": "",
"TLS": null
},
"TLS": null
}
java.lang.IllegalArgumentException: text cannot be null
如何使用GoLang使此POST请求成功,就像我使用POSTMAN Chrome扩展程序一样?
更新
我使用curl成功执行了相同的POST请求。
curl -X POST -u root:1 -H "Content-Type: application/json" --data-urlencode "INSERT INTO V SET name = 'jack', boss = #11:19" http://localhost:2480/command/GratefulDeadConcerts/sql
它的输出是:
{"result":[{"@type":"d","@rid":"#9:822","@version":1,"@class":"V","name":null}]}
更新2
当然,我不应该对curl
命令使用--data-urlencode
。
有效的curl命令是
curl -X POST -u root:1 -H "Content-Type: application/json" -d "INSERT INTO V SET name = 'jack', boss = #11:19" http://localhost:2480/command/GratefulDeadConcerts/sql
它的输出是:
{"result":[{"@type":"d","@rid":"#9:848","@version":1,"@class":"V","name":"jack","boss":"#11:19","@fieldTypes":"boss=x"}]}
我仍然不知道如何使用类似的GoLang POST请求。
更新3
url.QueryEscape
对我没有帮助。
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
)
func main() {
client := &http.Client{}
// 为什么这个stringData丢失了,并且没有通过POST请求传递?
stringData := `INSERT INTO V SET name = 'jack', boss = #11:19`
stringData = url.QueryEscape(stringData)
req, err := http.NewRequest("POST", "http://localhost:2480/command/GratefulDeadConcerts/sql", bytes.NewBufferString(stringData))
req.SetBasicAuth("root", "1")
req.Header.Set("Content-Type", "Content-Type: text/plain")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error : %s", err)
}
fmt.Println("resp")
fmt.Println(ToJson(resp))
var b bytes.Buffer
_, err = b.ReadFrom(resp.Body)
if err != nil {
log.Fatal("Error : %s", err)
}
fmt.Println(b.String())
}
func ToJson(obj interface{}) string {
b, err := json.MarshalIndent(&obj, "", " ")
if err != nil {
fmt.Printf("Error : %s", err)
}
strJson := string(b)
return strJson
}
结果是相同的:
resp
{
"Status": "500 Internal Server Error",
"StatusCode": 500,
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Cache-Control": [
"no-cache, no-store, max-age=0, must-revalidate"
],
"Connection": [
"Keep-Alive"
],
"Content-Length": [
"55"
],
"Content-Type": [
"text/plain; charset=utf-8"
],
"Date": [
"Mon Jun 08 19:39:12 MSK 2015"
],
"Pragma": [
"no-cache"
],
"Server": [
"OrientDB Server v.2.0.10 (build UNKNOWN@r; 2015-05-25 16:48:43+0000)"
]
},
"Body": {},
"ContentLength": 55,
"TransferEncoding": null,
"Close": false,
"Trailer": null,
"Request": {
"Method": "POST",
"URL": {
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "localhost:2480",
"Path": "/command/GratefulDeadConcerts/sql",
"RawQuery": "",
"Fragment": ""
},
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Authorization": [
"Basic cm9vdDox"
],
"Content-Type": [
"Content-Type: text/plain"
]
},
"Body": {
"Reader": {}
},
"ContentLength": 60,
"TransferEncoding": null,
"Close": false,
"Host": "localhost:2480",
"Form": null,
"PostForm": null,
"MultipartForm": null,
"Trailer": null,
"RemoteAddr": "",
"RequestURI": "",
"TLS": null
},
"TLS": null
}
java.lang.IllegalArgumentException: text cannot be null
另外,我在curl
命令中将content-type更改为text/plain
。
curl -X POST -u root:1 -H "Content-Type: text/plain" -d "INSERT INTO V SET name = 'jack', boss = #11:19" http://localhost:2480/command/GratefulDeadConcerts/sql
结果是相同的,curl
是可以的,但是golang
的POST请求不行。
更新4
我在尝试做什么?我正在为GO
应用程序实现OrientDB REST接口以执行查询。
英文:
I can do a POST request with string data, using POSTMAN chrome extension.
I need to do the same using golang
code.
But my Go
code loses string INSERT INTO V SET name = 'jack', boss = #11:19
and posts empty data to the server.
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
)
func main() {
client := &http.Client{}
// Why this stringData is lost and was not send with POST request?
stringData := `INSERT INTO V SET name = 'jack', boss = #11:19`
req, err := http.NewRequest("POST", "http://localhost:2480/command/GratefulDeadConcerts/sql", bytes.NewBufferString(stringData))
req.SetBasicAuth("root", "1")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error : %s", err)
}
fmt.Println("resp")
fmt.Println(ToJson(resp))
var b bytes.Buffer
_, err = b.ReadFrom(resp.Body)
if err != nil {
log.Fatal("Error : %s", err)
}
fmt.Println(b.String())
}
func ToJson(obj interface{}) string {
b, err := json.MarshalIndent(&obj, "", " ")
if err != nil {
fmt.Printf("Error : %s", err)
}
strJson := string(b)
return strJson
}
It gives output:
resp
{
"Status": "500 Internal Server Error",
"StatusCode": 500,
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Cache-Control": [
"no-cache, no-store, max-age=0, must-revalidate"
],
"Connection": [
"Keep-Alive"
],
"Content-Length": [
"55"
],
"Content-Type": [
"text/plain; charset=utf-8"
],
"Date": [
"Mon Jun 08 10:47:46 MSK 2015"
],
"Pragma": [
"no-cache"
],
"Server": [
"OrientDB Server v.2.0.10 (build UNKNOWN@r; 2015-05-25 16:48:43+0000)"
]
},
"Body": {},
"ContentLength": 55,
"TransferEncoding": null,
"Close": false,
"Trailer": null,
"Request": {
"Method": "POST",
"URL": {
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "localhost:2480",
"Path": "/command/GratefulDeadConcerts/sql",
"RawQuery": "",
"Fragment": ""
},
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Authorization": [
"Basic cm9vdDox"
]
},
"Body": {
"Reader": {}
},
"ContentLength": 46,
"TransferEncoding": null,
"Close": false,
"Host": "localhost:2480",
"Form": null,
"PostForm": null,
"MultipartForm": null,
"Trailer": null,
"RemoteAddr": "",
"RequestURI": "",
"TLS": null
},
"TLS": null
}
java.lang.IllegalArgumentException: text cannot be null
How to make this POST request work successfully, using GoLang, as I can do with POSTMAN chrome extension?
#Update
I made the same POST request successfully, using curl.
curl -X POST -u root:1 -H "Content-Type: application/json" --data-urlencode "INSERT INTO V SET name = 'jack', boss = #11:19" http://localhost:2480/command/GratefulDeadConcerts/sql
It outputs:
{"result":[{"@type":"d","@rid":"#9:822","@version":1,"@class":"V","name":null}]}
#Update 2
Of course, I should not use --data-urlencode
for curl
command.
The valid curl command is
curl -X POST -u root:1 -H "Content-Type: application/json" -d "INSERT INTO V SET name = 'jack', boss = #11:19" http://localhost:2480/command/GratefulDeadConcerts/sql
{"result":[{"@type":"d","@rid":"#9:848","@version":1,"@class":"V","name":"jack","boss":"#11:19","@fieldTypes":"boss=x"}]}
I still have no clue how to make the similar GoLang POST request.
#Update 3
url.QueryEscape
did not help me.
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
)
func main() {
client := &http.Client{}
// Why this stringData is lost and do not pass thgouht POST request?
stringData := `INSERT INTO V SET name = 'jack', boss = #11:19`
stringData = url.QueryEscape(stringData)
req, err := http.NewRequest("POST", "http://localhost:2480/command/GratefulDeadConcerts/sql", bytes.NewBufferString(stringData))
req.SetBasicAuth("root", "1")
req.Header.Set("Content-Type", "Content-Type: text/plain")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Error : %s", err)
}
fmt.Println("resp")
fmt.Println(ToJson(resp))
var b bytes.Buffer
_, err = b.ReadFrom(resp.Body)
if err != nil {
log.Fatal("Error : %s", err)
}
fmt.Println(b.String())
}
func ToJson(obj interface{}) string {
b, err := json.MarshalIndent(&obj, "", " ")
if err != nil {
fmt.Printf("Error : %s", err)
}
strJson := string(b)
return strJson
}
The result is the same:
resp
{
"Status": "500 Internal Server Error",
"StatusCode": 500,
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Cache-Control": [
"no-cache, no-store, max-age=0, must-revalidate"
],
"Connection": [
"Keep-Alive"
],
"Content-Length": [
"55"
],
"Content-Type": [
"text/plain; charset=utf-8"
],
"Date": [
"Mon Jun 08 19:39:12 MSK 2015"
],
"Pragma": [
"no-cache"
],
"Server": [
"OrientDB Server v.2.0.10 (build UNKNOWN@r; 2015-05-25 16:48:43+0000)"
]
},
"Body": {},
"ContentLength": 55,
"TransferEncoding": null,
"Close": false,
"Trailer": null,
"Request": {
"Method": "POST",
"URL": {
"Scheme": "http",
"Opaque": "",
"User": null,
"Host": "localhost:2480",
"Path": "/command/GratefulDeadConcerts/sql",
"RawQuery": "",
"Fragment": ""
},
"Proto": "HTTP/1.1",
"ProtoMajor": 1,
"ProtoMinor": 1,
"Header": {
"Authorization": [
"Basic cm9vdDox"
],
"Content-Type": [
"Content-Type: text/plain"
]
},
"Body": {
"Reader": {}
},
"ContentLength": 60,
"TransferEncoding": null,
"Close": false,
"Host": "localhost:2480",
"Form": null,
"PostForm": null,
"MultipartForm": null,
"Trailer": null,
"RemoteAddr": "",
"RequestURI": "",
"TLS": null
},
"TLS": null
}
java.lang.IllegalArgumentException: text cannot be null
Also, I changed content-type to text/plain
in curl
command.
curl -X POST -u root:1 -H "Content-Type: text/plain" -d "INSERT INTO V SET name = 'jack', boss = #11:19" http://localhost:2480/command/GratefulDeadConcerts/sql
{"result":[{"@type":"d","@rid":"#9:858","@version":1,"@class":"V","name":"jack","boss":"#11:19","@fieldTypes":"boss=x"}]}
The result is the same, it's ok with curl
, but not ok with golang
POST.
#Update 4
What am I trying to do? I am implementing OrientDB REST-interface for executing queries from a GO
application.
1: http://i.stack.imgur.com/GjdCs.png
答案1
得分: 0
阅读文档清楚地有所帮助。根据OrientDB文档1:
> 所有请求必须具有以下两个头部:
>
> 'Accept-Encoding': 'gzip,deflate'
> 'Content-Length': <content-length>
> 其中<content-length>是请求体的长度。
而你没有设置Accept-Encoding头部。很可能这就是你所需要的(而不是对请求体进行转义)。
1 http://orientdb.com/docs/last/orientdb.wiki/OrientDB-REST.html#headers
英文:
Reading the documentation clearly helps. From the OrientDB documentation documentation 1:
> All the requests must have these 2 headers:
>
> 'Accept-Encoding': 'gzip,deflate'
> 'Content-Length': <content-length>
> Where the <content-length> is the length of the request's body.
And you do not set the Accept-Encoding header. Most probably this is all you need (and not escaping the body).
1 http://orientdb.com/docs/last/orientdb.wiki/OrientDB-REST.html#headers
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论