Martin Niederl
Martin Niederl

Reputation: 759

Golang POST request to API returns 400, while the same request with e. g. Postman returns 200

In my Go application I use a Web API, which accepts a POST request and returns a token if it is successful.

The URL is the following: "https://accounts.zoho.com/apiauthtoken/nb/create?SCOPE=xxxx&EMAIL_ID=xxxx&PASSWORD=xxxx"

If I send this in Postman or any other tool, I get the status code 200 with the expected body, but in my go code the same request returns error code 400.

url := "https://accounts.zoho.com/apiauthtoken/nb/create?SCOPE=xxxx&EMAIL_ID=xxxx&PASSWORD=xxxx"

req, err := http.NewRequest("POST", url, nil)
log.Println(err)

res, err := client.Do(req)
log.Println(err)

defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
log.Println(err)

fmt.Println(res)
fmt.Println(string(body))

All errors are nil, but the res struct contains 400 Bad Request and the last output (of the body) is empty.

Output:

&{400 Bad Request 400 HTTP/1.1 1 1 map[Date:[Sat, 03 Mar 2018 16:48:35 GMT] Connection:[keep-alive] Set-Cookie:[a8c61fa0dc=5f224f2ab9d067cfce10fd0b7fae48bf; Path=/; Secure; HttpOnly] Server:[ZGS]] 0xc04225a080 -1 [chunked] false false map[] 0xc042034a00 0xc0421bc370}

I would appreciate any help, because I don't know where this problem comes from.

Upvotes: 1

Views: 3469

Answers (3)

Joe Qian
Joe Qian

Reputation: 493

Same question here, try to make a POST request with some QUERY params in url, which works fine in Postman but always got Http 400 in go debug with all the same params (Query params , post body ,headers and MD5 sign)

timeStr := time.Now().Format("2006-01-02 15:04:05")
serverUrlAll = serverUrlAll + "?token="+token+"&provider="+provide+"&timestamp="+timeStr+"&signature="+signature
contentBody := strings.NewReader(signString)
request, err := http.NewRequest("POST",serverUrlAll , contentBody)
if err != nil {
    return nil, err
}
request.Header.Set("Content-Type", "application/json")

Finally found the blank in query url will cause the error , remove the blank and it works in my case.

Upvotes: 0

PriyankRaj
PriyankRaj

Reputation: 1

I was facing the similar issue. The reason for 401 simply means the invalid authorization token. Later I noticed that Postman executes the Pre-request script that updates the header every time. You can pull in the same pre-request script code in golang and it works.

Upvotes: 0

Himanshu
Himanshu

Reputation: 12675

Url-encoded parameters should be provided in body parameter not as query string. So this can be a problem too. Set your paramters in body implementing io.Reader.

func NewRequest(method, url string, body io.Reader) (*Request, error)

Set the header Content-Type in your request before sending it using Client.Do.

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

Since postman is smart enough to set the headers for you. Thats why no error. The whole code becomes

package main

import (
    "log"
    "net/http"
    "net/url"
    "io/ioutil"
    "strings"
)
func main(){

    url := "https://accounts.zoho.com/apiauthtoken/nb/create"

    var data url.Values{}
    data.Set("SCOPE","xxxx")
    data.Add("EMAIL","xxxx")
    data.Add("PASSWORD","xxxx")
    req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    log.Println(err)

    res, err := client.Do(req)
    log.Println(err)

    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    log.Println(err)

    fmt.Println(res)
    fmt.Println(string(body))

}

Upvotes: 1

Related Questions