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.

191 lines
4.7 KiB

  1. package weed_server
  2. import (
  3. "bytes"
  4. "code.google.com/p/weed-fs/go/glog"
  5. "code.google.com/p/weed-fs/go/operation"
  6. "code.google.com/p/weed-fs/go/stats"
  7. "code.google.com/p/weed-fs/go/storage"
  8. "code.google.com/p/weed-fs/go/util"
  9. "encoding/json"
  10. "fmt"
  11. "net"
  12. "net/http"
  13. "path/filepath"
  14. "strconv"
  15. "strings"
  16. )
  17. var serverStats *stats.ServerStats
  18. func init() {
  19. serverStats = stats.NewServerStats()
  20. go serverStats.Start()
  21. }
  22. func writeJson(w http.ResponseWriter, r *http.Request, obj interface{}) (err error) {
  23. var bytes []byte
  24. if r.FormValue("pretty") != "" {
  25. bytes, err = json.MarshalIndent(obj, "", " ")
  26. } else {
  27. bytes, err = json.Marshal(obj)
  28. }
  29. if err != nil {
  30. return
  31. }
  32. callback := r.FormValue("callback")
  33. if callback == "" {
  34. w.Header().Set("Content-Type", "application/json")
  35. _, err = w.Write(bytes)
  36. } else {
  37. w.Header().Set("Content-Type", "application/javascript")
  38. if _, err = w.Write([]uint8(callback)); err != nil {
  39. return
  40. }
  41. if _, err = w.Write([]uint8("(")); err != nil {
  42. return
  43. }
  44. fmt.Fprint(w, string(bytes))
  45. if _, err = w.Write([]uint8(")")); err != nil {
  46. return
  47. }
  48. }
  49. return
  50. }
  51. // wrapper for writeJson - just logs errors
  52. func writeJsonQuiet(w http.ResponseWriter, r *http.Request, obj interface{}) {
  53. if err := writeJson(w, r, obj); err != nil {
  54. glog.V(0).Infof("error writing JSON %s: %s", obj, err.Error())
  55. }
  56. }
  57. func writeJsonError(w http.ResponseWriter, r *http.Request, err error) {
  58. w.WriteHeader(http.StatusInternalServerError)
  59. m := make(map[string]interface{})
  60. m["error"] = err.Error()
  61. writeJsonQuiet(w, r, m)
  62. }
  63. func debug(params ...interface{}) {
  64. glog.V(4).Infoln(params)
  65. }
  66. func secure(whiteList []string, f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
  67. return func(w http.ResponseWriter, r *http.Request) {
  68. if len(whiteList) == 0 {
  69. f(w, r)
  70. return
  71. }
  72. host, _, err := net.SplitHostPort(r.RemoteAddr)
  73. if err == nil {
  74. for _, ip := range whiteList {
  75. if ip == host {
  76. f(w, r)
  77. return
  78. }
  79. }
  80. }
  81. writeJsonQuiet(w, r, map[string]interface{}{"error": "No write permisson from " + host})
  82. }
  83. }
  84. func submitForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string) {
  85. m := make(map[string]interface{})
  86. if r.Method != "POST" {
  87. m["error"] = "Only submit via POST!"
  88. writeJsonQuiet(w, r, m)
  89. return
  90. }
  91. debug("parsing upload file...")
  92. fname, data, mimeType, isGzipped, lastModified, pe := storage.ParseUpload(r)
  93. if pe != nil {
  94. writeJsonError(w, r, pe)
  95. return
  96. }
  97. debug("assigning file id for", fname)
  98. assignResult, ae := operation.Assign(masterUrl, 1, r.FormValue("replication"), r.FormValue("collection"))
  99. if ae != nil {
  100. writeJsonError(w, r, ae)
  101. return
  102. }
  103. url := "http://" + assignResult.PublicUrl + "/" + assignResult.Fid
  104. if lastModified != 0 {
  105. url = url + "?ts=" + strconv.FormatUint(lastModified, 10)
  106. }
  107. debug("upload file to store", url)
  108. uploadResult, err := operation.Upload(url, fname, bytes.NewReader(data), isGzipped, mimeType)
  109. if err != nil {
  110. writeJsonError(w, r, err)
  111. return
  112. }
  113. m["fileName"] = fname
  114. m["fid"] = assignResult.Fid
  115. m["fileUrl"] = assignResult.PublicUrl + "/" + assignResult.Fid
  116. m["size"] = uploadResult.Size
  117. writeJsonQuiet(w, r, m)
  118. return
  119. }
  120. func deleteForClientHandler(w http.ResponseWriter, r *http.Request, masterUrl string) {
  121. r.ParseForm()
  122. fids := r.Form["fid"]
  123. ret, err := operation.DeleteFiles(masterUrl, fids)
  124. if err != nil {
  125. writeJsonError(w, r, err)
  126. return
  127. }
  128. writeJsonQuiet(w, r, ret)
  129. }
  130. func parseURLPath(path string) (vid, fid, filename, ext string, isVolumeIdOnly bool) {
  131. switch strings.Count(path, "/") {
  132. case 3:
  133. parts := strings.Split(path, "/")
  134. vid, fid, filename = parts[1], parts[2], parts[3]
  135. ext = filepath.Ext(filename)
  136. case 2:
  137. parts := strings.Split(path, "/")
  138. vid, fid = parts[1], parts[2]
  139. dotIndex := strings.LastIndex(fid, ".")
  140. if dotIndex > 0 {
  141. ext = fid[dotIndex:]
  142. fid = fid[0:dotIndex]
  143. }
  144. default:
  145. sepIndex := strings.LastIndex(path, "/")
  146. commaIndex := strings.LastIndex(path[sepIndex:], ",")
  147. if commaIndex <= 0 {
  148. vid, isVolumeIdOnly = path[sepIndex+1:], true
  149. return
  150. }
  151. dotIndex := strings.LastIndex(path[sepIndex:], ".")
  152. vid = path[sepIndex+1 : commaIndex]
  153. fid = path[commaIndex+1:]
  154. ext = ""
  155. if dotIndex > 0 {
  156. fid = path[commaIndex+1 : dotIndex]
  157. ext = path[dotIndex:]
  158. }
  159. }
  160. return
  161. }
  162. func statsCounterHandler(w http.ResponseWriter, r *http.Request) {
  163. m := make(map[string]interface{})
  164. m["Version"] = util.VERSION
  165. m["Counters"] = serverStats
  166. writeJsonQuiet(w, r, m)
  167. }
  168. func statsMemoryHandler(w http.ResponseWriter, r *http.Request) {
  169. m := make(map[string]interface{})
  170. m["Version"] = util.VERSION
  171. m["Memory"] = stats.MemStat()
  172. writeJsonQuiet(w, r, m)
  173. }