Edit: solved! The server was redirecting from /whales to /whales/, which transformed the request into a GET. My curl command had the trailing slash, but my form and Postman request did not.
My basic server always has "GET" as r.Method, even for post requests from Postman and html forms. r.Form is always an empty map.
My code:
func whaleHandler(w http.ResponseWriter, r *http.Request) {
fmt.Print(r.Method)
fmt.Print(r.Form)
}
func main() {
http.HandleFunc("/whales/", whaleHandler)
log.Fatal(http.ListenAndServe(":9002", nil))
}
And this prints:
GETmap[]
What am I doing wrong here? Thanks in advance, all!
Edit: everything works as expected with curl, but Postman and regular forms are still being treated like GET requests.
curl -d "Name=Barry" -X POST http://localhost:9002/whales/
results in:
POSTmap[]
,
and r.FormValue("Name")
spits out Barry
Sample form:
<form action="/whales" method="POST">
<div><input type="text" name="Name" placeholder="Name"></div>
<div><input type="text" name="Length" placeholder="Length"></div>
<div><input type="text" name="Type" placeholder="Type"></div>
<div><input type="submit" value="Save"></div>
</form>
And full output from fmt.Print(r)
, formatted a little for readability:
&{GET
/whales/
HTTP/1.1
1
1
map[
Accept:[
text/html,
application/xhtml+xml,
application/xml;q=0.9,*\/*;q=0.8
]
Accept-Language:[en-US,en;q=0.5]
Accept-Encoding:[gzip, deflate]
Cookie:[io=08-aNjAMs8v6ntatAAAA]
Connection:[keep-alive]
Upgrade-Insecure-Requests:[1]
User-Agent:[Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0] Referer:[http://localhost:9002/whales/create]
]
{}
<nil>
0
[]
false
localhost:9002
map[]
map[]
<nil>
map[]
/whales/
<nil>
<nil>
<nil>
0xc420162400}
Edit: Sample Postman request, which results in r.Method => "GET" Posting with Postman
You registered your handler under "/whales/", but your form action is "/whales" (without trailing slash). Go will redirect requests from /whales to /whales/ in this configuration -- most clients choose to follow via GET requests.
Either register the handler for "/whales", or change the form action to "/whales/", depending on other URLs you wish to handle. E.g., if you need to handle /whales/willy, leave the handler as-is and change the form action.
You need to call Request.ParseForm()
(or something that calls it indirectly, such as Request.FormValue()
), until then Request.Form
will not contain form data. See possible duplicate Getting No data received for go language form.
This is documented at Request.Form
:
// Form contains the parsed form data, including both the URL
// field's query parameters and the POST or PUT form data.
// This field is only available after ParseForm is called.
// The HTTP client ignores Form and uses Body instead.
Form url.Values
If you change your handler to this:
func whaleHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.Method)
fmt.Println(r.Form)
if err := r.ParseForm(); err != nil {
fmt.Println("Error parsing form:", err)
}
fmt.Println(r.Form)
}
And performing the curl
command:
curl -d "Name=Barry" -X POST http://localhost:9002/whales/
Output will be:
POST
map[]
map[Name:[Barry]]