How to set up web server to perform POST Request in Go?

Issue

I want to perform a POST Request in Go with the following code:

package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
func main() {
  const myurl string = "http://localhost:8000/"
  request := strings.NewReader(`
 {
    "Name":"Tom",
    "Age":"20" 
 }
`)
  response, _ := http.Post(myurl, "application/json", request)
  content, _ := ioutil.ReadAll(response.Body)
  fmt.Println(string(content))
  defer response.Body.Close()
}

But I’m not sure how to initiate the Web Server to perform the POST Request, this is the implementation I made, in another tab in Visual Studio Code:

package main
import (
"log"
"net/http"
 )
func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){})
  log.Fatal(http.ListenAndServe(":8000", nil))
}

What am I missing in order to perform the POST Request?

Edit: I brought everything into one tab in VSCode and made the necessary changes, but how does the post request get executed since only HandleFunc and ListenAndServe are defined in main function?

package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
 )
func post(w http.ResponseWriter, r *http.Request) {
  const myurl string = "http://localhost:8000/"
  request := strings.NewReader(`
  {
    "Name":"Tom",
    "Age":"20" 
  }
`)
  response, err := http.Post(myurl, "application/json", request)
  content, err := ioutil.ReadAll(response.Body)
  if err != nil {
     panic(err)
  }
  fmt.Println(string(content))
  defer response.Body.Close()
  }
func main() {
  http.HandleFunc("/", post)
  log.Fatal(http.ListenAndServe(":8000", nil))
}

Solution

Here is a basic example of how you could go about it. I am using the same program to run both, the server and the client. This is just for demonstration purposes. You can of course make them separate programs.

// use struct to represent the data 
// to recieve and send
type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}
// run the example
func main() {
    // start the server in a goroutine
    go server()

    // wait 1 second to give the server time to start
    time.Sleep(time.Second)

    // make a post request
    if err := client(); err != nil {
        fmt.Println(err)
    }
}
// basic web server to receive a request and 
// decode the body into a user struct
func server() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost  {
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            return
        }

        user := &Person{}
        err := json.NewDecoder(r.Body).Decode(user)
        if err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }

        fmt.Println("got user:", user)
        w.WriteHeader(http.StatusCreated)
    })

    if err := http.ListenAndServe(":8080", nil); err != http.ErrServerClosed {
        panic(err)
    }
}
// a simple client that posts a user to the server
func client() error {
    user := &Person{
        Name: "John",
        Age:  30,
    }

    b := new(bytes.Buffer)
    err := json.NewEncoder(b).Encode(user)
    if err != nil {
        return err
    }

    resp, err := http.Post("http://localhost:8080/", "application/json", b)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    fmt.Println(resp.Status)
    return nil
}

Here is the working example: https://go.dev/play/p/34GT04jy_uA

Answered By – The Fool

Answer Checked By – Pedro (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.