进行HTTP表单解析-返回空的slice / empty值?

I have written a simple web application in Go that needs to read values of an HTTP form (username, password) etc. However, I found that the values were empty when printed. len(r.Form) and len(r.Form["password"]) both return 0.

I have called r.ParseForm() in the application before trying to read the fields and I'm using Postman to send the requests. Tested on both Linux and macOS.

The code I am using to test this is some example code from the Astaxie golang web tutorial. I have attached my Postman request. It looks like this so far:

package main

import (
    "fmt"
    "html/template"
    "log"
    "net/http"
    "strings"
    "time"
)

func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() //Parse url parameters passed, then parse the response packet for the POST body (request body)
    // attention: If you do not call ParseForm method, the following data can not be obtained form
    fmt.Println(r.Form) // print information on server side.
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["url_long"])
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, "Hello astaxie!") // write data to response
}

func login(w http.ResponseWriter, r *http.Request) {
    fmt.Println("method:", r.Method) //get request method
    if r.Method == "GET" {
        t, _ := template.ParseFiles("login.gtpl")
        t.Execute(w, nil)
    } else {
        r.ParseForm()
        time.Sleep(3 * time.Second)
        // logic part of log in
        fmt.Println("username:", len(r.Form))
        fmt.Println("password:", len(r.Form["password"]))
    }

}

func main() {
    http.HandleFunc("/", sayhelloName) // setting router rule
    http.HandleFunc("/login", login)
    err := http.ListenAndServe(":9090", nil) // setting listening port
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

Any suggestions on what to do next?

Thanks!

try changing the content-type on your Postman request from form-data to x-www-form-urlencoded

Because according to the docs on r.ParseForm() the body won't be parsed unless it's x-www-form-urlencoded

For other HTTP methods, or when the Content-Type is not application/x-www-form-urlencoded, the request Body is not read, and r.PostForm is initialized to a non-nil, empty value.

I suggest you first check content type then read form data with request.FormValue("example") if you use form you always check key is valid in map or not and if you don't It's make a runtime error.

func login(w http.ResponseWriter, r *http.Request) {
    fmt.Println("method:", r.Method) //get request method
    if r.Method == "GET" {
        t, _ := template.ParseFiles("login.gtpl")
        t.Execute(w, nil)
    } else {
        fmt.Println("username:", r.FormValue("username"))
        fmt.Println("password:", r.FormValue("password"))
    }

}