Currently trying to create a multipart upload request to upload a png along with some extra body params. The server is returning the response:
The request body did not contain the specified number of bytes. Got 142,827, expected 146,836
So obviously something is going wrong with the calculation. I can't for the life of me work out how to actually manually count the content length of the body and file correctly for the request. See below my code for sending request:
func signUp(email, username, password, profilePath string) account {
session := createClient()
capToke := captchaToken(session)
solved := solveCaptcha(capToke, "example.com")
if solved == failed {
panic("Solve Failed")
}
extraParams := map[string]string{
"Username": username,
"Age": string(random(18, 21)),
"Gender": "1",
"EmailAddress": email,
"Password": password,
"ConfirmPassword": password,
"g-recaptcha-response": solved,
"Recaptcha": "",
"ReceiveNewsletter": "false",
}
req, err := makeFileUploadRequest("https://example.com", extraParams, "ProfileImage", profilePath)
if err != nil {
panic(err)
}
req.Header.Set("Host", "example.com")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.Header.Set("Accept-Language", "en-US,en;q=0.5")
req.Header.Set("Accept-Encoding", "gzip, deflate, br")
req.Header.Set("Referer", "https://example.com")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Upgrade-Insecure-Requests", "1")
client := createClient()
resp, err := client.Do(req)
defer resp.Body.Close()
if err != nil {
panic(err)
} else {
var bodyContent []byte
fmt.Println(resp.StatusCode)
fmt.Println(resp.Header)
resp.Body.Read(bodyContent)
resp.Body.Close()
fmt.Println(bodyContent)
}
var acc account
acc.email = email
acc.password = password
acc.username = username
return acc
}
func makeFileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
fileContents, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
fi, err := file.Stat()
if err != nil {
return nil, err
}
file.Close()
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
for key, val := range params {
_ = writer.WriteField(key, val)
}
err = writer.Close()
if err != nil {
return nil, err
}
part, err := writer.CreateFormFile(paramName, fi.Name())
if err != nil {
return nil, err
}
ht, _ := http.NewRequest("POST", uri, body)
ht.Header.Set("Content-Type", writer.FormDataContentType())
writer.Close()
return ht, err
}
The error is on these lines:
ht, _ := http.NewRequest("POST", uri, body)
ht.Header.Set("Content-Type", writer.FormDataContentType())
writer.Close()
The call to NewRequest recognizes that the body is a bytes.Buffer and sets the content length header using the current size of the buffer.
The final multipart boundary is written to the request body in the call to writer.Close(). This boundary is not included in the content length set previously in the call to NewRequest.
To fix the problem, close the writer before creating the request:
writer.Close()
ht, _ := http.NewRequest("POST", uri, body)
ht.Header.Set("Content-Type", writer.FormDataContentType())