使用golang发送带有字符串数据的POST请求。

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

POST golang request with string data

问题

我可以使用POSTMAN Chrome扩展程序进行字符串数据的POST请求。

使用golang发送带有字符串数据的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.

使用golang发送带有字符串数据的POST请求。

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

huangapple
  • 本文由 发表于 2015年6月8日 15:01:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/30702948.html
匿名

发表评论

匿名网友

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

确定