curl.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package helpers
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. "os"
  9. "strings"
  10. "time"
  11. )
  12. var (
  13. ErrCurlGetStatus = error(&CurlGetStatusError{})
  14. )
  15. type CurlGetOpts struct {
  16. ExpectStatusCode int
  17. Headers map[string][]string
  18. Timeout time.Duration
  19. }
  20. type CurlGetStatusError struct {
  21. Expected int
  22. Received int
  23. }
  24. func (e *CurlGetStatusError) Is(err error) bool {
  25. if _, ok := err.(*CurlGetStatusError); !ok {
  26. return false
  27. }
  28. return true
  29. }
  30. func (e *CurlGetStatusError) Error() string {
  31. return fmt.Sprintf("CurlGet: expected %d, received %d", e.Expected, e.Received)
  32. }
  33. func CurlDownload(ctx context.Context, url string, opts *CurlGetOpts, fileName string, filePath ...string) error {
  34. dir := strings.Join(filePath, string(os.PathSeparator))
  35. f := strings.Join([]string{dir, fileName}, string(os.PathSeparator))
  36. if _, err := os.Stat(f); !errors.Is(err, os.ErrNotExist) {
  37. return os.ErrExist
  38. }
  39. var (
  40. b []byte
  41. err error
  42. )
  43. if b, err = CurlGet(ctx, url, opts); err != nil {
  44. return err
  45. }
  46. if err := os.MkdirAll(dir, os.ModePerm); err != nil {
  47. return err
  48. }
  49. return os.WriteFile(f, b, 0644)
  50. }
  51. func CurlGet(ctx context.Context, url string, opts *CurlGetOpts) ([]byte, error) {
  52. if opts == nil {
  53. opts = &CurlGetOpts{
  54. ExpectStatusCode: http.StatusOK,
  55. Headers: nil,
  56. Timeout: time.Second * 60,
  57. }
  58. }
  59. var b []byte
  60. ctx, cancel := context.WithTimeout(ctx, opts.Timeout)
  61. defer cancel()
  62. req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
  63. if err != nil {
  64. return b, err
  65. }
  66. req.Header = opts.Headers
  67. rcl := &http.Client{}
  68. var resp *http.Response
  69. resp, err = rcl.Do(req)
  70. if err != nil {
  71. return b, err
  72. }
  73. defer resp.Body.Close()
  74. b, err = io.ReadAll(resp.Body)
  75. if err != nil {
  76. return b, err
  77. }
  78. if opts.ExpectStatusCode > 0 {
  79. if resp.StatusCode != opts.ExpectStatusCode {
  80. return b, error(&CurlGetStatusError{
  81. Expected: opts.ExpectStatusCode,
  82. Received: resp.StatusCode,
  83. })
  84. }
  85. }
  86. return b, nil
  87. }