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