Search code examples
gohttpmultipartform-data

How to POST basic JSON as multipart/form-data in Golang


I'm dealing with a very frustrating endpoint that requires me to use multipart/form-data as the Content-Type to POST, even though the endpoint just realistically wants basic key:value text for any parts of the form. I'd like to use the basic Golang http library.

Unfortunately, any example I've otherwise seen is for more complicated types - files, images, videos, etc. What I have on my end to put into the body is a simple map[string]interface{} where the interface{} is simple go types - string, bool, int, float64, etc. How do I convert this interface into something that the NewRequest func will take? Thanks!


bodyInput := map[string]interface{}{"client_id":"abc123", "you_ok": false, "jwt_token":"psojioajf.sjfiofijw.asdisaoetcetc"}

req, err := http.NewRequest(http.MethodPost, "https://my-website.com/endpoint/path", ???) // replace ???
if err != nil {
          // handle error 
}

req.Header.Set("Content-Type", "multipart/form-data")
    
client := http.Client{}
rsp, err := client.Do(req)
// deal with the rest


Solution

  • Based on this answer for a different question, I was able to figure out what I needed. I had to use the multipart library and also properly set a boundary on the header.

    
    import (
       "mime/multipart"
    )
    
    bodyInput := map[string]interface{}{"client_id":"abc123", "you_ok": false, "jwt_token":"psojioajf.sjfiofijw.asdisaoetcetc"}
    
    
    reqBody := new(bytes.Buffer)
    mp := multipart.NewWriter(reqBody)
    for k, v := range bodyInput {
      str, ok := v.(string) 
      if !ok {
        return fmt.Errorf("converting %v to string", v) 
      }
      mp.WriteField(k, str)
    }
    mp.Close()
    
    req, err := http.NewRequest(http.MethodPost, "https://my-website.com/endpoint/path", reqBody)
    if err != nil {
    // handle err
    }
    
    req.Header["Content-Type"] = []string{mp.FormDataContentType()}