I have a REST endpoint provided by a Java Spring Boot app that I am trying to hit with a simple Go (go1.8 darwin/amd64) program. I have tried to hit it in 2 separate ways:
const (
LOCAL_BASE = "http://localhost:11400"
ADD_FUNDS_ENDPOINT = "/sub-accounts/%d/add-funds"
)
type InputArgumentsJson struct {
Amount float64 `json:"amount"`
BufferAmount float64 `json:"bufferAmount"`
FromSubAccountID int `json:"fromSubAccountId"`
}
...
// set up json body
inputArguments := &InputArgumentsJson{Amount: 1100, BufferAmount: 0,
FromSubAccountID: spendFundId}
bytes := new(bytes.Buffer)
json.NewEncoder(bytes).Encode(inputArguments)
// set up the url to call
endpoint := fmt.Sprintf(ADD_FUNDS_ENDPOINT, billSetAsideId)
url := LOCAL_BASE + endpoint
client := &http.Client{}
req, err := http.NewRequest("POST", url, bytes)
if err != nil {
fmt.Println("ERROR WHILE BUILDING REQUEST")
fmt.Println(err)
}
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
fmt.Println("ERROR WHILE MAKING REQUEST")
fmt.Println(err)
}
fmt.Println(resp)
and:
resp, err := http.Post(url, "application/json; charset=utf-8", bytes)
if err != nil {
fmt.Println("ERROR WHILE MAKING REQUEST")
fmt.Println(err)
}
fmt.Println(resp)
I added a print out to see if the URL and JSON body were right and they appeared to be:
fmt.Printf("
Making request to %s with:
%s
", url, bytes)
printed out
Making request to http://localhost:11400/sub-accounts/167/add-funds with:
{"amount":1100,"bufferAmount":0,"fromSubAccountId":166}
but I am getting a 403 Forbidden when running it.
I can hit this endpoint without fail using both Postman and the following Curl command:
curl -H "Content-Type: application/json" -X POST -d '{"amount":1100,"bufferAmount":0,"fromSubAccountId":166}' http://localhost:11400/sub-accounts/167/add-funds
Does anyone have any thoughts on what I may be missing here? To add further to the intrigue I can successfully hit a different GET endpoint from the Go program.
Thanks in advance!
Edited to show that I was catching the errors and the surrounding logic for creating the URL and JSON body
You did not show what bytes
is but that's most probably the problem: both NewRequest
and Post
take an io.Reader
and read the body from that reader. This reading typically can happen only once (think of a stream). When you fmt.Printf("%s")
the io.Reader
this printing will consume the content (most probably by invoking a String() method) and the actual request is done with an empty body.
Always show whole code. And do not try to read twice from an io.Reader.
I assume there are 2 Go apps and runs on a different host, which results a CORS problem. Consider adding the Access-Control-Allow-Origin
at your service with your client's host.
w.Header().Set("Access-Control-Allow-Origin", "*")
You can change *
with specified hostname which your client application runs.
OMG....I just found the problem. It turned out that it was failing (as I was expecting), but it was erroneously returning it as a 403 rather than a 400. Ugh...sometimes when you stare at something for a long time the obvious things completely escape notice.
you should set User-Agent in request header
req, _ := http.NewRequest(http.MethodGet, urlString, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")