AppTest
AppTest

Reputation: 501

Sending a JSON object to a Go server from a webpage

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 (
    "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))
}

This works when I use curl.

curl --header "Content-Type: application/json" -d "{\"rating\":3}" 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:  {"rating":3}

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

<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>

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:  

Upvotes: 0

Views: 157

Answers (1)

Thundercat
Thundercat

Reputation: 120931

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("/getRes", getRes)

or by posting to the path /getRes/:

fetch("getRes/", {

Upvotes: 2

Related Questions