Search code examples
apipostgocommentsimgur

Imgur API: POST comment in GO


I'm trying to POST a comment to imgur through the Imgur API. But I can't make the payload right. I have looked through Imgur's page about this and they showed that it should be coded like I have in strings.NewReader. The imageID is nP0uKKO

func HandleComment(w http.ResponseWriter, r *http.Request){
parts := strings.Split(r.URL.Path, "/")

switch r.Method {

case "POST":
    // URL for POSTing comment
    url := "https://api.imgur.com/3/comment"

    // Authorization key
    token := "Bearer " + os.Getenv("TOKEN")

    // Payload
    payload := strings.NewReader("------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"image_id\"\r\n\r\nnP0uKKO\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"comment\"\r\n\r\nI'm a giraffe!\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--")

    // Get body and http status code
    body, status := DoStuff(parts[2], url, payload, token)

    // If status is not OK
    if status != 200 {
        http.Error(w, "Could not post comment", status)
    } else {
        fmt.Fprintln(w, string(body))
    }

DoStuff() does this

func DoStuff(method string, url string, body io.Reader, key string) ([]byte, int) {

    // New request
    req, err := http.NewRequest(method, url, body)
    if err != nil {
        fmt.Println(err)
    }

    // Add header with 'key' authorization
    req.Header.Add("authorization", key)

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println(err)
    }

    defer res.Body.Close()

    imgBody, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
    }

    return imgBody, res.StatusCode
} 

I just get this error

 {
   data: {
           error: "The parameter, image_id, is required.",
           request: "/3/comment",
           method: "POST"
   },
   success: false,
   status: 400
 }

Solution

  • The thing missing is the Content-Type header. You can modify your code like this:

    In your handler HandleComment you can define the headers you want to pass to the request

    case "POST":
        // URL for POSTing comment
        url := "https://api.imgur.com/3/comment"
    
        // Authorization key
        token := "Bearer " + os.Getenv("TOKEN")
    
        // Payload
        payload := strings.NewReader("------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"image_id\"\r\n\r\nnP0uKKO\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"comment\"\r\n\r\nI'm a giraffe!\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--")
        // Headers
        headers := map[string]string{
            "Authorization": token,
            "Content-Type":  "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
        }
    
        // Get body and http status code
        body, status := DoStuff(parts[2], url, payload, headers)
    
        // If status is not OK
        if status != 200 {
            http.Error(w, "Could not post comment", status)
        } else {
            fmt.Fprintln(w, string(body))
        }
    

    Update DoStuff to read and pass the headers

    func DoStuff(method string, url string, body io.Reader, headers map[string]string) ([]byte, int) {
    
        // New request
        req, err := http.NewRequest(method, url, body)
        if err != nil {
          fmt.Println(err)
        }
    
        // Add headers
        for k, v := range headers {
          req.Header.Add(k, v)
        }
    
        res, err := http.DefaultClient.Do(req)
        if err != nil {
          fmt.Println(err)
        }
    
        defer res.Body.Close()
    
        imgBody, err := ioutil.ReadAll(res.Body)
        if err != nil {
          fmt.Println(err)
        }
    
        return imgBody, res.StatusCode
    }
    

    I would suggest instead of using multipart/form-data; you might utilize the json content type. It is easier to manage and more readable

    // Payload
    payload := strings.NewReader("{\"image_id\": \"nP0uKKO\", \"comment\": \"I'm a giraffe!\"}")
    // Headers
    headers := map[string]string{
        "Authorization": token,
        "Content-Type":  "application/json",
    }