Home > Mobile >  How to write such curl request in golang for youtrack rest api?
How to write such curl request in golang for youtrack rest api?

Time:07-14

I am writing golang client with youtrack REST I have written the most most path of API. But faced problem with attaching files to an Issue. So, here there is small and good doc https://www.jetbrains.com/help/youtrack/devportal/api-usecase-attach-files.html

The using the commands from this and other doc pages are worked with curl(via terminal) I am newby in golang, but have to write in this language.

func createForm(form map[string]string) (string, io.Reader, error) {
    body := new(bytes.Buffer)
    mp := multipart.NewWriter(body)
    defer mp.Close()
    for key, val := range form {
        if strings.HasPrefix(val, "@") {
            val = val[1:]
            file, err := os.Open(val)
            if err != nil {
                return "", nil, err
            }
            defer file.Close()
            part, err := mp.CreateFormFile(key, val)
            if err != nil {
                return "", nil, err
            }
            io.Copy(part, file)
        } else {
            mp.WriteField(key, val)
        }
    }
    return mp.FormDataContentType(), body, nil
}

func AttachFileToIssue(path string, issueID string) {
    form := map[string]string{"image": "@image.jpeg", "key": "KEY"}
    _, body, err := createForm(form)
    if err != nil {
        panic(err)
    }

    req, err := http.NewRequest("POST", youTrackUrl "/api/issues/" issueID "/attachments?fields=id,name", body)

    if err != nil {
        // handle err
    }
    req.Header.Set("Authorization", "Bearer " youTrackToken)
    req.Header.Set("Content-Type", "multipart/form-data")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        // handle err
    }
    fmt.Println(resp)
    if resp.StatusCode == http.StatusOK {
        bodyBytes, err := io.ReadAll(resp.Body)
        if err != nil {
            log.Fatal(err)
        }
        bodyString := string(bodyBytes)
        fmt.Println(bodyString)
    }
    defer func(Body io.ReadCloser) {
        err := Body.Close()
        if err != nil {

        }
    }(resp.Body)
}

The error code is:

{400 Bad Request 400 HTTP/1.1 1 1 map[Access-Control-Expose-Headers:[Location] Cache-Control:[no-cache, no-store, no-transform, must-revalidate] Content-Length:[110] Content-Type:[application/json;charset=utf-8] Date:[Sun, 10 Jul 2022 10:28:24 GMT] Referrer-Policy:[same-origin] Server:[YouTrack] X-Content-Type-Options:[nosniff] X-Frame-Options:[SAMEORIGIN] X-Xss-Protection:[1; mode=block]] 0xc0001cc100 110 [] false false map[] 0xc000254000 <nil>}

I used wireshark to check what is wrong, the problem is with mime-part, something missing.

The curl REQUEST:

curl -v -i -F upload=@/Users/jetbrains/Downloads/youtrack.txt \
-F upload=@/Users/jetbrains/Downloads/youtrack_new.jpeg \
-H 'Authorization: Bearer perm:cm9vdA==.MjZGZWI=.WB02vjX0cM2ltLTJXUE3VOWHpJYYNx' \
-H 'Content-Type: multipart/form-data' \
-X POST 'https://example.youtrack.cloud/api/issues/99-500/attachments?fields=id,name'

CodePudding user response:

Ana Bartasheva is right!

The solution:

func createForm(form map[string]string) (string, io.Reader, error) {
    body := new(bytes.Buffer)
    mp := multipart.NewWriter(body)
    defer func(mp *multipart.Writer) {
        err := mp.Close()
        if err != nil {

        }
    }(mp)
    var file *os.File
    for key, val := range form {
        if strings.HasPrefix(val, "@") {
            val = val[1:]
            file, err := os.Open(val)
            if err != nil {
                return "", nil, err
            }
            part, err := mp.CreateFormFile(key, val)
            if err != nil {
                return "", nil, err
            }
            _, err = io.Copy(part, file)
            if err != nil {
                return "", nil, err
            }
        } else {
            err := mp.WriteField(key, val)
            if err != nil {
                return "", nil, err
            }
        }
    }
    defer func(file *os.File) {
        err := file.Close()
        if err != nil {

        }
    }(file)

    return mp.FormDataContentType(), body, nil
}

func AttachFileToIssue(path string, issueID string) string {
    form := map[string]string{"path": "@"   path}
    mp, body, err := createForm(form)
    if err != nil {
        panic(err)
    }
    req, err := http.NewRequest("POST", youTrackUrl "/api/issues/" issueID "/attachments?fields=id,name", body)

    if err != nil {
        // handle err
    }

    req.Header.Set("Authorization", "Bearer " youTrackToken)
    req.Header.Set("Content-Type", mp)

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        // handle err
    }
    if resp.StatusCode == http.StatusOK {
        bodyBytes, err := io.ReadAll(resp.Body)
        if err != nil {
            log.Fatal(err)
        }
        bodyString := string(bodyBytes)
        return bodyString
    }
    defer func(Body io.ReadCloser) {
        err := Body.Close()
        if err != nil {

        }
    }(resp.Body)
    return ""
}
  • Related