将一个 JSON 对象从网页发送到 Go 服务器

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

Sending a JSON object to a Go server from a webpage

问题

我正在尝试将一个JSON对象发送到我的Go服务器。我查看了所有我能找到的示例,但无法弄清楚我漏掉了什么。

服务器代码如下:

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"text/template"
)

func handler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles("list.html")
	if err != nil {

		fmt.Println("Failed to parse")
		log.Fatal(err)
	}

	m := make(map[string]string)

	m["Title"] = "A title"

	err = t.Execute(w, m)
	if err != nil {

		fmt.Println("Failed to execute")
		log.Fatal(err)
	}
}

func getRes(w http.ResponseWriter, r *http.Request) {
	fmt.Println("HEADER: ", r.Header)
	fmt.Println("CL: ", r.ContentLength)
	fmt.Println("CT: ", r.Header.Get("Content-Type"))
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("B: ", string(b))

}

func main() {
	fmt.Println("Starting")
	http.HandleFunc("/", handler)
	http.HandleFunc("/getRes/", getRes)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

当我使用curl时,它可以正常工作。

curl --header "Content-Type: application/json" -d "{\"rating\":3}" http://localhost:8080/getRes/

我得到以下响应:

HEADER:  map[Accept:[*/*] Content-Length:[12] Content-Type:[application/json] User-Agent:[curl/7.58.0]]
CL:  12
CT:  application/json
B:  {"rating":3}

但是,当我使用以下HTML/JavaScript代码时,它不起作用:

<html>
	<head>
		<script>

        window.onload = function() {

            fetch("getRes", {
                
                "method": "POST",
                
                "body": JSON.stringify({
                    "rating": 5
                }),
                
                "headers": {
                    "Content-type": "application/json"
                }
            });
        }
		</script>
	</head>
	<body>
		{{.Title}}
	</body></html>

我得到一个响应,但它是空的,内容长度为零:

HEADER:  map[Accept:[*/*] Accept-Encoding:[gzip, deflate, br] Accept-Language:[en-GB,en-US;q=0.9,en;q=0.8] Connection:[keep-alive] Referer:[http://localhost:8080/] Sec-Fetch-Mode:[cors] Sec-Fetch-Site:[same-origin] User-Agent:[Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36]]
CL:  0
CT:  
B:  
英文:

I'm trying to send a JSON object to my Go server. I've looked at all the examples I could find and can't figure out what I'm missing.

The server code:

package main

import (
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;text/template&quot;
)

func handler(w http.ResponseWriter, r *http.Request) {
	t, err := template.ParseFiles(&quot;list.html&quot;)
	if err != nil {

		fmt.Println(&quot;Failed to parse&quot;)
		log.Fatal(err)
	}

	m := make(map[string]string)

	m[&quot;Title&quot;] = &quot;A title&quot;

	err = t.Execute(w, m)
	if err != nil {

		fmt.Println(&quot;Failed to execute&quot;)
		log.Fatal(err)
	}
}

func getRes(w http.ResponseWriter, r *http.Request) {
	fmt.Println(&quot;HEADER: &quot;, r.Header)
	fmt.Println(&quot;CL: &quot;, r.ContentLength)
	fmt.Println(&quot;CT: &quot;, r.Header.Get(&quot;Content-Type&quot;))
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(&quot;B: &quot;, string(b))

}

func main() {
	fmt.Println(&quot;Starting&quot;)
	http.HandleFunc(&quot;/&quot;, handler)
	http.HandleFunc(&quot;/getRes/&quot;, getRes)
	log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))
}

This works when I use curl.

curl --header &quot;Content-Type: application/json&quot; -d &quot;{\&quot;rating\&quot;:3}&quot; http://localhost:8080/getRes/

I get the response:

HEADER:  map[Accept:[*/*] Content-Length:[12] Content-Type:[application/json] User-Agent:[curl/7.58.0]]
CL:  12
CT:  application/json
B:  {&quot;rating&quot;:3}

It doesn't work when I use the following HTML/Javascript code:

&lt;html&gt;
	&lt;head&gt;
		&lt;script&gt;

        window.onload = function() {

            fetch(&quot;getRes&quot;, {
                
                &quot;method&quot;: &quot;POST&quot;,
                
                &quot;body&quot;: JSON.stringify({
                    &quot;rating&quot;: 5
                }),
                
                &quot;headers&quot;: {
                    &quot;Content-type&quot;: &quot;application/json&quot;
                }
            });
        }
		&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
	{{.Title}}
&lt;/body&gt;&lt;/html&gt;

I get a response but it's empty with a content length of zero:

HEADER:  map[Accept:[*/*] Accept-Encoding:[gzip, deflate, br] Accept-Language:[en-GB,en-US;q=0.9,en;q=0.8] Connection:[keep-alive] Referer:[http://localhost:8080/] Sec-Fetch-Mode:[cors] Sec-Fetch-Site:[same-origin] User-Agent:[Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36]]
CL:  0
CT:  
B:  

答案1

得分: 2

页面将数据以POST方式提交到路径/getres。由于没有为/getres注册处理程序,但为/getres/注册了处理程序,所以mux将客户端重定向到/getres/。重定向是一个没有请求体的GET请求。

ServeMux文档描述了重定向的行为:

> 如果已经注册了一个子树,并且收到了一个请求,请求中的路径是子树根路径但没有尾部斜杠,ServeMux会将该请求重定向到子树根路径(添加尾部斜杠)。

修复方法是为路径/getres注册处理程序:

http.HandleFunc("/getRes", getRes)

或者将数据以POST方式提交到路径/getRes/

fetch("getRes/", {
英文:

The page POSTs to the path /getres. The mux redirects the client to /getres/ because there is not a handler for registered for /getres, but there is for /getres/. The redirect is a GET request with no body.

The ServeMux documentation describes the redirect:

> If a subtree has been registered and a request is received naming the subtree root without its trailing slash, ServeMux redirects that request to the subtree root (adding the trailing slash).

Fix by registering the handler for the path /getres

http.HandleFunc(&quot;/getRes&quot;, getRes)

or by posting to the path /getRes/:

fetch(&quot;getRes/&quot;, {

huangapple
  • 本文由 发表于 2021年6月21日 08:09:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/68060997.html
匿名

发表评论

匿名网友

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

确定