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.

154 lines
4.4 KiB

  1. package weed_server
  2. import (
  3. "code.google.com/p/weed-fs/go/glog"
  4. "code.google.com/p/weed-fs/go/operation"
  5. "code.google.com/p/weed-fs/go/util"
  6. "encoding/json"
  7. "errors"
  8. "github.com/syndtr/goleveldb/leveldb"
  9. "io"
  10. "io/ioutil"
  11. "math/rand"
  12. "net/http"
  13. "net/url"
  14. "strings"
  15. )
  16. func (fs *FilerServer) filerHandler(w http.ResponseWriter, r *http.Request) {
  17. switch r.Method {
  18. case "GET":
  19. fs.GetOrHeadHandler(w, r, true)
  20. case "HEAD":
  21. fs.GetOrHeadHandler(w, r, false)
  22. case "DELETE":
  23. fs.DeleteHandler(w, r)
  24. case "PUT":
  25. fs.PostHandler(w, r)
  26. case "POST":
  27. fs.PostHandler(w, r)
  28. }
  29. }
  30. func (fs *FilerServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request, isGetMethod bool) {
  31. fileId, err := fs.FindFile(r.URL.Path)
  32. if err == leveldb.ErrNotFound {
  33. w.WriteHeader(http.StatusNotFound)
  34. return
  35. }
  36. parts := strings.Split(fileId, ",")
  37. if len(parts) != 2 {
  38. glog.V(1).Infoln("Invalid fileId", fileId)
  39. w.WriteHeader(http.StatusNotFound)
  40. return
  41. }
  42. lookup, lookupError := operation.Lookup(fs.master, parts[0])
  43. if lookupError != nil {
  44. glog.V(1).Infoln("Invalid lookup", lookupError.Error())
  45. w.WriteHeader(http.StatusNotFound)
  46. return
  47. }
  48. if len(lookup.Locations) == 0 {
  49. glog.V(1).Infoln("Can not find location for volume", parts[0])
  50. w.WriteHeader(http.StatusNotFound)
  51. return
  52. }
  53. urlLocation := lookup.Locations[rand.Intn(len(lookup.Locations))].PublicUrl
  54. u, _ := url.Parse("http://" + urlLocation + "/" + fileId)
  55. request := &http.Request{
  56. Method: r.Method,
  57. URL: u,
  58. Proto: r.Proto,
  59. ProtoMajor: r.ProtoMajor,
  60. ProtoMinor: r.ProtoMinor,
  61. Header: r.Header,
  62. Body: r.Body,
  63. Host: r.Host,
  64. ContentLength: r.ContentLength,
  65. }
  66. glog.V(3).Infoln("retrieving from", u)
  67. resp, do_err := util.Do(request)
  68. if do_err != nil {
  69. glog.V(0).Infoln("failing to connect to volume server", do_err.Error())
  70. w.WriteHeader(http.StatusInternalServerError)
  71. writeJsonError(w, r, do_err)
  72. return
  73. }
  74. defer resp.Body.Close()
  75. io.Copy(w, resp.Body)
  76. }
  77. func (fs *FilerServer) PostHandler(w http.ResponseWriter, r *http.Request) {
  78. query := r.URL.Query()
  79. assignResult, ae := operation.Assign(fs.master, 1, query.Get("replication"), fs.collection)
  80. if ae != nil {
  81. glog.V(0).Infoln("failing to assign a file id", ae.Error())
  82. w.WriteHeader(http.StatusInternalServerError)
  83. writeJsonError(w, r, ae)
  84. return
  85. }
  86. u, _ := url.Parse("http://" + assignResult.PublicUrl + "/" + assignResult.Fid)
  87. request := &http.Request{
  88. Method: r.Method,
  89. URL: u,
  90. Proto: r.Proto,
  91. ProtoMajor: r.ProtoMajor,
  92. ProtoMinor: r.ProtoMinor,
  93. Header: r.Header,
  94. Body: r.Body,
  95. Host: r.Host,
  96. ContentLength: r.ContentLength,
  97. }
  98. resp, do_err := util.Do(request)
  99. if do_err != nil {
  100. glog.V(0).Infoln("failing to connect to volume server", do_err.Error())
  101. w.WriteHeader(http.StatusInternalServerError)
  102. writeJsonError(w, r, do_err)
  103. return
  104. }
  105. defer resp.Body.Close()
  106. resp_body, ra_err := ioutil.ReadAll(resp.Body)
  107. if ra_err != nil {
  108. glog.V(0).Infoln("failing to upload to volume server", ra_err.Error())
  109. w.WriteHeader(http.StatusInternalServerError)
  110. writeJsonError(w, r, ra_err)
  111. return
  112. }
  113. var ret operation.UploadResult
  114. unmarshal_err := json.Unmarshal(resp_body, &ret)
  115. if unmarshal_err != nil {
  116. glog.V(0).Infoln("failing to read upload resonse", string(resp_body))
  117. w.WriteHeader(http.StatusInternalServerError)
  118. writeJsonError(w, r, unmarshal_err)
  119. return
  120. }
  121. if ret.Error != "" {
  122. glog.V(0).Infoln("failing to post to volume server", ra_err.Error())
  123. w.WriteHeader(http.StatusInternalServerError)
  124. writeJsonError(w, r, errors.New(ret.Error))
  125. return
  126. }
  127. if db_err := fs.CreateFile(r.URL.Path, assignResult.Fid); db_err != nil {
  128. operation.DeleteFile(fs.master, assignResult.Fid) //clean up
  129. glog.V(0).Infoln("failing to write to filer server", db_err.Error())
  130. w.WriteHeader(http.StatusInternalServerError)
  131. writeJsonError(w, r, db_err)
  132. }
  133. w.WriteHeader(http.StatusCreated)
  134. }
  135. func (fs *FilerServer) DeleteHandler(w http.ResponseWriter, r *http.Request) {
  136. isForceDirectoryRemoval := r.FormValue("force") == "true" // force remove for directories
  137. fid, isFile, err := fs.Delete(r.URL.Path, isForceDirectoryRemoval)
  138. if err == nil {
  139. if isFile {
  140. err = operation.DeleteFile(fs.master, fid)
  141. }
  142. }
  143. if err != nil {
  144. glog.V(1).Infoln("deleting", r.URL.Path, ":", err.Error())
  145. w.WriteHeader(http.StatusAccepted)
  146. } else {
  147. w.WriteHeader(http.StatusInternalServerError)
  148. }
  149. }