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

273 lines
5.5 KiB

9 years ago
10 years ago
7 years ago
10 years ago
10 years ago
  1. package util
  2. import (
  3. "bytes"
  4. "compress/gzip"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "net/http"
  11. "net/url"
  12. "strings"
  13. "time"
  14. "github.com/chrislusf/seaweedfs/weed/security"
  15. )
  16. var (
  17. client *http.Client
  18. Transport *http.Transport
  19. )
  20. func init() {
  21. Transport = &http.Transport{
  22. MaxIdleConnsPerHost: 1024,
  23. }
  24. client = &http.Client{
  25. Transport: Transport,
  26. Timeout: 5 * time.Second,
  27. }
  28. }
  29. func PostBytes(url string, body []byte) ([]byte, error) {
  30. r, err := client.Post(url, "application/octet-stream", bytes.NewReader(body))
  31. if err != nil {
  32. return nil, fmt.Errorf("Post to %s: %v", url, err)
  33. }
  34. defer r.Body.Close()
  35. if r.StatusCode >= 400 {
  36. return nil, fmt.Errorf("%s: %s", url, r.Status)
  37. }
  38. b, err := ioutil.ReadAll(r.Body)
  39. if err != nil {
  40. return nil, fmt.Errorf("Read response body: %v", err)
  41. }
  42. return b, nil
  43. }
  44. func Post(url string, values url.Values) ([]byte, error) {
  45. r, err := client.PostForm(url, values)
  46. if err != nil {
  47. return nil, err
  48. }
  49. defer r.Body.Close()
  50. b, err := ioutil.ReadAll(r.Body)
  51. if r.StatusCode >= 400 {
  52. if err != nil {
  53. return nil, fmt.Errorf("%s: %d - %s", url, r.StatusCode, string(b))
  54. } else {
  55. return nil, fmt.Errorf("%s: %s", url, r.Status)
  56. }
  57. }
  58. if err != nil {
  59. return nil, err
  60. }
  61. return b, nil
  62. }
  63. // github.com/chrislusf/seaweedfs/unmaintained/repeated_vacuum/repeated_vacuum.go
  64. // may need increasing http.Client.Timeout
  65. func Get(url string) ([]byte, error) {
  66. r, err := client.Get(url)
  67. if err != nil {
  68. return nil, err
  69. }
  70. defer r.Body.Close()
  71. b, err := ioutil.ReadAll(r.Body)
  72. if r.StatusCode >= 400 {
  73. return nil, fmt.Errorf("%s: %s", url, r.Status)
  74. }
  75. if err != nil {
  76. return nil, err
  77. }
  78. return b, nil
  79. }
  80. func Head(url string) (http.Header, error) {
  81. r, err := client.Head(url)
  82. if err != nil {
  83. return nil, err
  84. }
  85. defer r.Body.Close()
  86. if r.StatusCode >= 400 {
  87. return nil, fmt.Errorf("%s: %s", url, r.Status)
  88. }
  89. return r.Header, nil
  90. }
  91. func Delete(url string, jwt security.EncodedJwt) error {
  92. req, err := http.NewRequest("DELETE", url, nil)
  93. if jwt != "" {
  94. req.Header.Set("Authorization", "BEARER "+string(jwt))
  95. }
  96. if err != nil {
  97. return err
  98. }
  99. resp, e := client.Do(req)
  100. if e != nil {
  101. return e
  102. }
  103. defer resp.Body.Close()
  104. body, err := ioutil.ReadAll(resp.Body)
  105. if err != nil {
  106. return err
  107. }
  108. switch resp.StatusCode {
  109. case http.StatusNotFound, http.StatusAccepted, http.StatusOK:
  110. return nil
  111. }
  112. m := make(map[string]interface{})
  113. if e := json.Unmarshal(body, m); e == nil {
  114. if s, ok := m["error"].(string); ok {
  115. return errors.New(s)
  116. }
  117. }
  118. return errors.New(string(body))
  119. }
  120. func GetBufferStream(url string, values url.Values, allocatedBytes []byte, eachBuffer func([]byte)) error {
  121. r, err := client.PostForm(url, values)
  122. if err != nil {
  123. return err
  124. }
  125. defer r.Body.Close()
  126. if r.StatusCode != 200 {
  127. return fmt.Errorf("%s: %s", url, r.Status)
  128. }
  129. for {
  130. n, err := r.Body.Read(allocatedBytes)
  131. if n > 0 {
  132. eachBuffer(allocatedBytes[:n])
  133. }
  134. if err != nil {
  135. if err == io.EOF {
  136. return nil
  137. }
  138. return err
  139. }
  140. }
  141. }
  142. func GetUrlStream(url string, values url.Values, readFn func(io.Reader) error) error {
  143. r, err := client.PostForm(url, values)
  144. if err != nil {
  145. return err
  146. }
  147. defer r.Body.Close()
  148. if r.StatusCode != 200 {
  149. return fmt.Errorf("%s: %s", url, r.Status)
  150. }
  151. return readFn(r.Body)
  152. }
  153. func DownloadFile(fileUrl string) (filename string, header http.Header, rc io.ReadCloser, e error) {
  154. response, err := client.Get(fileUrl)
  155. if err != nil {
  156. return "", nil, nil, err
  157. }
  158. header = response.Header
  159. contentDisposition := response.Header["Content-Disposition"]
  160. if len(contentDisposition) > 0 {
  161. idx := strings.Index(contentDisposition[0], "filename=")
  162. if idx != -1 {
  163. filename = contentDisposition[0][idx+len("filename="):]
  164. filename = strings.Trim(filename, "\"")
  165. }
  166. }
  167. rc = response.Body
  168. return
  169. }
  170. func Do(req *http.Request) (resp *http.Response, err error) {
  171. return client.Do(req)
  172. }
  173. func NormalizeUrl(url string) string {
  174. if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
  175. return url
  176. }
  177. return "http://" + url
  178. }
  179. func ReadUrl(fileUrl string, offset int64, size int, buf []byte, isReadRange bool) (n int64, e error) {
  180. req, _ := http.NewRequest("GET", fileUrl, nil)
  181. if isReadRange {
  182. req.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+int64(size)))
  183. } else {
  184. req.Header.Set("Accept-Encoding", "gzip")
  185. }
  186. r, err := client.Do(req)
  187. if err != nil {
  188. return 0, err
  189. }
  190. defer r.Body.Close()
  191. if r.StatusCode >= 400 {
  192. return 0, fmt.Errorf("%s: %s", fileUrl, r.Status)
  193. }
  194. var reader io.ReadCloser
  195. switch r.Header.Get("Content-Encoding") {
  196. case "gzip":
  197. reader, err = gzip.NewReader(r.Body)
  198. defer reader.Close()
  199. default:
  200. reader = r.Body
  201. }
  202. var i, m int
  203. for {
  204. m, err = reader.Read(buf[i:])
  205. if m == 0 {
  206. return
  207. }
  208. i += m
  209. n += int64(m)
  210. if err == io.EOF {
  211. return n, nil
  212. }
  213. if e != nil {
  214. return n, e
  215. }
  216. }
  217. }
  218. func ReadUrlAsStream(fileUrl string, offset int64, size int, fn func(data []byte)) (n int64, e error) {
  219. req, _ := http.NewRequest("GET", fileUrl, nil)
  220. req.Header.Add("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+int64(size)))
  221. r, err := client.Do(req)
  222. if err != nil {
  223. return 0, err
  224. }
  225. defer r.Body.Close()
  226. if r.StatusCode >= 400 {
  227. return 0, fmt.Errorf("%s: %s", fileUrl, r.Status)
  228. }
  229. var m int
  230. buf := make([]byte, 64*1024)
  231. for {
  232. m, err = r.Body.Read(buf)
  233. if m == 0 {
  234. return
  235. }
  236. fn(buf[:m])
  237. n += int64(m)
  238. if err == io.EOF {
  239. return n, nil
  240. }
  241. if e != nil {
  242. return n, e
  243. }
  244. }
  245. }