如何在Golang中编写用于YouTrack REST API的curl请求?

huangapple go评论115阅读模式
英文:

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

问题

我正在使用YouTrack REST编写Golang客户端。我已经编写了大部分API的路径,但在将文件附加到问题时遇到了问题。所以,这里有一个小而好的文档https://www.jetbrains.com/help/youtrack/devportal/api-usecase-attach-files.html

使用这个文档和其他文档页面中的命令在curl(通过终端)中可以工作。我是Golang的新手,但必须使用这种语言编写。

  1. func createForm(form map[string]string) (string, io.Reader, error) {
  2. body := new(bytes.Buffer)
  3. mp := multipart.NewWriter(body)
  4. defer mp.Close()
  5. for key, val := range form {
  6. if strings.HasPrefix(val, "@") {
  7. val = val[1:]
  8. file, err := os.Open(val)
  9. if err != nil {
  10. return "", nil, err
  11. }
  12. defer file.Close()
  13. part, err := mp.CreateFormFile(key, val)
  14. if err != nil {
  15. return "", nil, err
  16. }
  17. io.Copy(part, file)
  18. } else {
  19. mp.WriteField(key, val)
  20. }
  21. }
  22. return mp.FormDataContentType(), body, nil
  23. }
  24. func AttachFileToIssue(path string, issueID string) {
  25. form := map[string]string{"image": "@image.jpeg", "key": "KEY"}
  26. _, body, err := createForm(form)
  27. if err != nil {
  28. panic(err)
  29. }
  30. req, err := http.NewRequest("POST", youTrackUrl+"/api/issues/"+issueID+"/attachments?fields=id,name", body)
  31. if err != nil {
  32. // handle err
  33. }
  34. req.Header.Set("Authorization", "Bearer "+youTrackToken)
  35. req.Header.Set("Content-Type", "multipart/form-data")
  36. resp, err := http.DefaultClient.Do(req)
  37. if err != nil {
  38. // handle err
  39. }
  40. fmt.Println(resp)
  41. if resp.StatusCode == http.StatusOK {
  42. bodyBytes, err := io.ReadAll(resp.Body)
  43. if err != nil {
  44. log.Fatal(err)
  45. }
  46. bodyString := string(bodyBytes)
  47. fmt.Println(bodyString)
  48. }
  49. defer func(Body io.ReadCloser) {
  50. err := Body.Close()
  51. if err != nil {
  52. }
  53. }(resp.Body)
  54. }

错误代码是:

  1. {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>}

我使用Wireshark检查了问题所在,问题出在mime-part上,有些东西丢失了。

curl请求:

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

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.

  1. func createForm(form map[string]string) (string, io.Reader, error) {
  2. body := new(bytes.Buffer)
  3. mp := multipart.NewWriter(body)
  4. defer mp.Close()
  5. for key, val := range form {
  6. if strings.HasPrefix(val, &quot;@&quot;) {
  7. val = val[1:]
  8. file, err := os.Open(val)
  9. if err != nil {
  10. return &quot;&quot;, nil, err
  11. }
  12. defer file.Close()
  13. part, err := mp.CreateFormFile(key, val)
  14. if err != nil {
  15. return &quot;&quot;, nil, err
  16. }
  17. io.Copy(part, file)
  18. } else {
  19. mp.WriteField(key, val)
  20. }
  21. }
  22. return mp.FormDataContentType(), body, nil
  23. }
  24. func AttachFileToIssue(path string, issueID string) {
  25. form := map[string]string{&quot;image&quot;: &quot;@image.jpeg&quot;, &quot;key&quot;: &quot;KEY&quot;}
  26. _, body, err := createForm(form)
  27. if err != nil {
  28. panic(err)
  29. }
  30. req, err := http.NewRequest(&quot;POST&quot;, youTrackUrl+&quot;/api/issues/&quot;+issueID+&quot;/attachments?fields=id,name&quot;, body)
  31. if err != nil {
  32. // handle err
  33. }
  34. req.Header.Set(&quot;Authorization&quot;, &quot;Bearer &quot;+youTrackToken)
  35. req.Header.Set(&quot;Content-Type&quot;, &quot;multipart/form-data&quot;)
  36. resp, err := http.DefaultClient.Do(req)
  37. if err != nil {
  38. // handle err
  39. }
  40. fmt.Println(resp)
  41. if resp.StatusCode == http.StatusOK {
  42. bodyBytes, err := io.ReadAll(resp.Body)
  43. if err != nil {
  44. log.Fatal(err)
  45. }
  46. bodyString := string(bodyBytes)
  47. fmt.Println(bodyString)
  48. }
  49. defer func(Body io.ReadCloser) {
  50. err := Body.Close()
  51. if err != nil {
  52. }
  53. }(resp.Body)
  54. }

The error code is:

  1. {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 &lt;nil&gt;}

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

The curl REQUEST:

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

答案1

得分: 0

Ana Bartasheva是正确的!

解决方案:

  1. func createForm(form map[string]string) (string, io.Reader, error) {
  2. body := new(bytes.Buffer)
  3. mp := multipart.NewWriter(body)
  4. defer func(mp *multipart.Writer) {
  5. err := mp.Close()
  6. if err != nil {
  7. }
  8. }(mp)
  9. var file *os.File
  10. for key, val := range form {
  11. if strings.HasPrefix(val, "@") {
  12. val = val[1:]
  13. file, err := os.Open(val)
  14. if err != nil {
  15. return "", nil, err
  16. }
  17. part, err := mp.CreateFormFile(key, val)
  18. if err != nil {
  19. return "", nil, err
  20. }
  21. _, err = io.Copy(part, file)
  22. if err != nil {
  23. return "", nil, err
  24. }
  25. } else {
  26. err := mp.WriteField(key, val)
  27. if err != nil {
  28. return "", nil, err
  29. }
  30. }
  31. }
  32. defer func(file *os.File) {
  33. err := file.Close()
  34. if err != nil {
  35. }
  36. }(file)
  37. return mp.FormDataContentType(), body, nil
  38. }
  39. func AttachFileToIssue(path string, issueID string) string {
  40. form := map[string]string{"path": "@" + path}
  41. mp, body, err := createForm(form)
  42. if err != nil {
  43. panic(err)
  44. }
  45. req, err := http.NewRequest("POST", youTrackUrl+"/api/issues/"+issueID+"/attachments?fields=id,name", body)
  46. if err != nil {
  47. // handle err
  48. }
  49. req.Header.Set("Authorization", "Bearer "+youTrackToken)
  50. req.Header.Set("Content-Type", mp)
  51. resp, err := http.DefaultClient.Do(req)
  52. if err != nil {
  53. // handle err
  54. }
  55. if resp.StatusCode == http.StatusOK {
  56. bodyBytes, err := io.ReadAll(resp.Body)
  57. if err != nil {
  58. log.Fatal(err)
  59. }
  60. bodyString := string(bodyBytes)
  61. return bodyString
  62. }
  63. defer func(Body io.ReadCloser) {
  64. err := Body.Close()
  65. if err != nil {
  66. }
  67. }(resp.Body)
  68. return ""
  69. }

以上是给问题中的代码进行的翻译。

英文:

Ana Bartasheva is right!

The solution:

  1. func createForm(form map[string]string) (string, io.Reader, error) {
  2. body := new(bytes.Buffer)
  3. mp := multipart.NewWriter(body)
  4. defer func(mp *multipart.Writer) {
  5. err := mp.Close()
  6. if err != nil {
  7. }
  8. }(mp)
  9. var file *os.File
  10. for key, val := range form {
  11. if strings.HasPrefix(val, &quot;@&quot;) {
  12. val = val[1:]
  13. file, err := os.Open(val)
  14. if err != nil {
  15. return &quot;&quot;, nil, err
  16. }
  17. part, err := mp.CreateFormFile(key, val)
  18. if err != nil {
  19. return &quot;&quot;, nil, err
  20. }
  21. _, err = io.Copy(part, file)
  22. if err != nil {
  23. return &quot;&quot;, nil, err
  24. }
  25. } else {
  26. err := mp.WriteField(key, val)
  27. if err != nil {
  28. return &quot;&quot;, nil, err
  29. }
  30. }
  31. }
  32. defer func(file *os.File) {
  33. err := file.Close()
  34. if err != nil {
  35. }
  36. }(file)
  37. return mp.FormDataContentType(), body, nil
  38. }
  39. func AttachFileToIssue(path string, issueID string) string {
  40. form := map[string]string{&quot;path&quot;: &quot;@&quot; + path}
  41. mp, body, err := createForm(form)
  42. if err != nil {
  43. panic(err)
  44. }
  45. req, err := http.NewRequest(&quot;POST&quot;, youTrackUrl+&quot;/api/issues/&quot;+issueID+&quot;/attachments?fields=id,name&quot;, body)
  46. if err != nil {
  47. // handle err
  48. }
  49. req.Header.Set(&quot;Authorization&quot;, &quot;Bearer &quot;+youTrackToken)
  50. req.Header.Set(&quot;Content-Type&quot;, mp)
  51. resp, err := http.DefaultClient.Do(req)
  52. if err != nil {
  53. // handle err
  54. }
  55. if resp.StatusCode == http.StatusOK {
  56. bodyBytes, err := io.ReadAll(resp.Body)
  57. if err != nil {
  58. log.Fatal(err)
  59. }
  60. bodyString := string(bodyBytes)
  61. return bodyString
  62. }
  63. defer func(Body io.ReadCloser) {
  64. err := Body.Close()
  65. if err != nil {
  66. }
  67. }(resp.Body)
  68. return &quot;&quot;
  69. }

huangapple
  • 本文由 发表于 2022年7月12日 00:47:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/72941957.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定