How to send post form data through a http client? - http

I have a problem with post request, needed to send simple form data through http client.
http.PostForm() is not ok because I need to set my own user agent and other headers.
Here is the sample
func main() {
formData := url.Values{
"form1": {"value1"},
"form2": {"value2"},
}
client := &http.Client{}
//Not working, the post data is not a form
req, err := http.NewRequest("POST", "http://test.local/api.php", strings.NewReader(formData.Encode()))
if err != nil {
log.Fatalln(err)
}
req.Header.Set("User-Agent", "Golang_Super_Bot/0.1")
resp, err := client.Do(req)
if err != nil {
log.Fatalln(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
log.Println(string(body))
}

You also need to set the content type to application/x-www-form-urlencoded which corresponds to the encoding used by Value.Encode().
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
This is mentioned as one of the things done by Client.PostForm.

Related

Sending form-data in a POST request in golang

I'm trying to send form-data by making a post request. The api works fine (I've tested on postman), but I'm not sure why I'm having trouble to do it in golang. The form-data contains a task field and a file field. But if I do the following I get Bad Request. Any ideas why I might be getting this? Thanks in advance.
// Create new buffer and writer
buf := new(bytes.Buffer)
w := multipart.NewWriter(buf)
// read data from file
var fdata []byte
if fd, e := os.Open(pdf); e != nil {
log.Fatal(e)
} else {
fd.Read(fdata)
}
// create file field and write
part, err := w.CreateFormFile("file", pdf)
if err != nil {
log.Fatal(err)
}
part.Write(fdata)
// create the task field and write
part, err = w.CreateFormField("task")
if err != nil {
log.Fatal(err)
}
part.Write([]byte(os.Getenv("task")))
w.Close()
// Create a new request
req, err := http.NewRequest("POST", fmt.Sprintf("https://%v/v1/upload",os.Getenv("server")), buf)
// Set content type header
req.Header.Add("Content-Type", "multipart/form-data")
// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// other stuff

Go http request redirect

I am writing an API whichs has to redirect incoming requests to another service, the response must be forwarded to the original requester.
I figured a simple function like below should do the trick, but I was wrong.
I receive the data from my redirected response, however when I send it back to the initial request I receive this response without any data Could not get response. Error: socket hang up
If I try to execute the very same request using postman straight to the redirect URL it works perfectly fine.
func initialAssetsHandler(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Println(err)
return
}
resp, err := http.Post(conf.redirectURL, "application/json", bytes.NewReader(body))
if err != nil {
log.Error(err)
}
defer resp.Body.Close()
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
log.Info(string(buf.Bytes()))
var data json.RawMessage
if err = json.NewDecoder(resp.Body).Decode(&data); err != nil {
fmt.Println(err)
return
}
helper.SendJsonRaw(w, 200, data)
}
Here is the SendJsonRaw function:
func SendJsonRaw(w http.ResponseWriter, status int, r json.RawMessage) error {
w.Header().Set(HeaderContentType, MimeApplicationJSON)
w.WriteHeader(status)
_, err := w.Write(r)
return err
}
The r.Body is read by the json decoder up to EOF, then when you pass it to the redirect request it looks empty to the http.Client and therefore it sends no body. You need to retain the content of the body.
For example you can do the following:
func initialAssetsHandler(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Println(err)
return
}
var initialAssets TagAssets
if err := json.Unmarshal(&initialAssets, body); err != nil {
if !strings.Contains(err.Error(), "json: invalid use of ,string struct tag, trying to unmarshal") {
helper.SendJsonError(w, http.StatusBadRequest, err)
return
}
}
resp, err := http.Post(conf.redirectURL, "application/json", bytes.NewReader(body))
if err != nil {
log.Error(err)
}
defer resp.Body.Close()
log.Info(resp)
var data json.RawMessage
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
fmt.Println(err)
return
}
helper.SendJsonOk(w, data)
}

Convert string from args/flags to json then send to post http request as body

I'm trying to pass the values ​​I get in the arg / flag --BODY="{user: root}" as the body of the post request I'm trying to do, I've already used json.Marshal and even so I wasn't successful, thanks for the help !
Code below:
func Custom(method string, url string, token string, data string) {
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
req.Header.Add("Authorization", FormatBearerToken(token))
// req.Header.Set("Content-Type", "application/json")
if err != nil {
log.Println("Request failed, ", err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Println(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
log.Println("response Body:", string(body))
}

Connection reset by peer GO

I'm trying to do a request in GO but I always receive "Connection reset by peer" error. The following code shows how I'm doing the request:
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
client := = &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
fmt.Println(resp.Body)
...and I receive:
Get https://example.com: read tcp 1.2.3.4:1234->5.6.7.8:5678: read: connection reset by peer
When I do curl https://example.com I receive response form the server.
Why can't I do the request in GO?
Your code works if I use it against a URL like https://example.com. Are you sure you are passing it the correct URL?
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://example.com"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println(err)
return
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("OK")
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
return
}
str := string(bytes[:])
fmt.Printf("%s", str)
}

Golang: Simultaneous function Calls for http post request

I need to call multiple URL at the same time. My functions get called at the same time (in milli seconds) but the moment I add a Http post request to the code it gets called one after the other. Below is the code:
Check(url1)
Check(url2)
func Check(xurl string) {
nowstartx := time.Now()
startnanos := nowstartx.UnixNano()
nowstart := startnanos / 1000000
fmt.Println(nowstart)
json = {"name" : "test"}
req, err := http.NewRequest("POST", xurl, bytes.NewBuffer(json))
req.Header.Set("X-Custom-Header", "myvalue")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
} else {
defer resp.Body.Close()
body, _ = ioutil.ReadAll(resp.Body)
}
}
Appreciate help, I need to get the same time (in milliseconds) when I run the program.
This is achieved by using Goroutines
go Check(url1)
go Check(url2)
func Check(xurl string) {
nowstartx := time.Now()
startnanos := nowstartx.UnixNano()
nowstart := startnanos / 1000000
fmt.Println(nowstart)
json = {"name" : "test"}
req, err := http.NewRequest("POST", xurl, bytes.NewBuffer(json))
req.Header.Set("X-Custom-Header", "myvalue")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
} else {
defer resp.Body.Close()
body, _ = ioutil.ReadAll(resp.Body)
}
}

Resources