You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.go 2.6 kB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package cdsapi
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "path/filepath"
  8. "strings"
  9. "gitlink.org.cn/cloudream/common/utils/http2"
  10. "gitlink.org.cn/cloudream/common/utils/io2"
  11. "gitlink.org.cn/cloudream/common/utils/math2"
  12. "gitlink.org.cn/cloudream/common/utils/serder"
  13. )
  14. func MakeIPFSFilePath(fileHash string) string {
  15. return filepath.Join("ipfs", fileHash)
  16. }
  17. func ParseJSONResponse[TBody any](resp *http.Response) (TBody, error) {
  18. var ret TBody
  19. contType := resp.Header.Get("Content-Type")
  20. if strings.Contains(contType, http2.ContentTypeJSON) {
  21. var err error
  22. if ret, err = serder.JSONToObjectStreamEx[TBody](resp.Body); err != nil {
  23. return ret, fmt.Errorf("parsing response: %w", err)
  24. }
  25. return ret, nil
  26. }
  27. cont, err := io.ReadAll(resp.Body)
  28. if err != nil {
  29. return ret, fmt.Errorf("unknow response content type: %s, status: %d", contType, resp.StatusCode)
  30. }
  31. strCont := string(cont)
  32. return ret, fmt.Errorf("unknow response content type: %s, status: %d, body(prefix): %s", contType, resp.StatusCode, strCont[:math2.Min(len(strCont), 200)])
  33. }
  34. func WriteStream(dst io.Writer, src io.Reader) (int64, error) {
  35. sent := int64(0)
  36. buf := make([]byte, 1024*4)
  37. header := make([]byte, 4)
  38. for {
  39. n, err := src.Read(buf)
  40. if n > 0 {
  41. binary.LittleEndian.PutUint32(header, uint32(n))
  42. err := io2.WriteAll(dst, header)
  43. if err != nil {
  44. return sent, err
  45. }
  46. sent += int64(n)
  47. }
  48. if err == io.EOF {
  49. binary.LittleEndian.PutUint32(header, uint32(0))
  50. err := io2.WriteAll(dst, header)
  51. if err != nil {
  52. return sent, err
  53. }
  54. return sent, nil
  55. }
  56. if err != nil {
  57. errData := []byte(err.Error())
  58. header := make([]byte, 4)
  59. binary.LittleEndian.PutUint32(header, uint32(-len(errData)))
  60. // 不管有没有成功
  61. io2.WriteAll(dst, header)
  62. io2.WriteAll(dst, errData)
  63. return sent, err
  64. }
  65. }
  66. }
  67. func ReadStream(src io.Reader) io.ReadCloser {
  68. pr, pw := io.Pipe()
  69. buf := make([]byte, 1024*4)
  70. go func() {
  71. for {
  72. _, err := io.ReadFull(src, buf[:4])
  73. if err != nil {
  74. pw.CloseWithError(err)
  75. break
  76. }
  77. h := int32(binary.LittleEndian.Uint32(buf[:4]))
  78. if h == 0 {
  79. pw.Close()
  80. break
  81. }
  82. if h < 0 {
  83. _, err := io.ReadFull(src, buf[:-h])
  84. if err != nil {
  85. pw.CloseWithError(err)
  86. break
  87. }
  88. pw.CloseWithError(fmt.Errorf(string(buf[:-h])))
  89. break
  90. }
  91. _, err = io.ReadFull(src, buf[:h])
  92. if err != nil {
  93. pw.CloseWithError(err)
  94. break
  95. }
  96. _, err = pw.Write(buf[:h])
  97. if err != nil {
  98. pw.Close()
  99. break
  100. }
  101. }
  102. }()
  103. return pr
  104. }