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.

128 lines
3.3 KiB

9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
6 years ago
5 years ago
9 years ago
5 years ago
6 years ago
5 years ago
  1. package weed_server
  2. import (
  3. "context"
  4. "io"
  5. "mime"
  6. "net/http"
  7. "path/filepath"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/chrislusf/seaweedfs/weed/filer2"
  12. "github.com/chrislusf/seaweedfs/weed/glog"
  13. "github.com/chrislusf/seaweedfs/weed/images"
  14. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  15. "github.com/chrislusf/seaweedfs/weed/stats"
  16. "github.com/chrislusf/seaweedfs/weed/util"
  17. )
  18. func (fs *FilerServer) GetOrHeadHandler(w http.ResponseWriter, r *http.Request, isGetMethod bool) {
  19. path := r.URL.Path
  20. isForDirectory := strings.HasSuffix(path, "/")
  21. if isForDirectory && len(path) > 1 {
  22. path = path[:len(path)-1]
  23. }
  24. entry, err := fs.filer.FindEntry(context.Background(), util.FullPath(path))
  25. if err != nil {
  26. if path == "/" {
  27. fs.listDirectoryHandler(w, r)
  28. return
  29. }
  30. if err == filer_pb.ErrNotFound {
  31. glog.V(1).Infof("Not found %s: %v", path, err)
  32. stats.FilerRequestCounter.WithLabelValues("read.notfound").Inc()
  33. w.WriteHeader(http.StatusNotFound)
  34. } else {
  35. glog.V(0).Infof("Internal %s: %v", path, err)
  36. stats.FilerRequestCounter.WithLabelValues("read.internalerror").Inc()
  37. w.WriteHeader(http.StatusInternalServerError)
  38. }
  39. return
  40. }
  41. if entry.IsDirectory() {
  42. if fs.option.DisableDirListing {
  43. w.WriteHeader(http.StatusMethodNotAllowed)
  44. return
  45. }
  46. fs.listDirectoryHandler(w, r)
  47. return
  48. }
  49. if isForDirectory {
  50. w.WriteHeader(http.StatusNotFound)
  51. return
  52. }
  53. if len(entry.Chunks) == 0 {
  54. glog.V(1).Infof("no file chunks for %s, attr=%+v", path, entry.Attr)
  55. stats.FilerRequestCounter.WithLabelValues("read.nocontent").Inc()
  56. w.WriteHeader(http.StatusNoContent)
  57. return
  58. }
  59. w.Header().Set("Accept-Ranges", "bytes")
  60. w.Header().Set("Last-Modified", entry.Attr.Mtime.Format(http.TimeFormat))
  61. // mime type
  62. mimeType := entry.Attr.Mime
  63. if mimeType == "" {
  64. if ext := filepath.Ext(entry.Name()); ext != "" {
  65. mimeType = mime.TypeByExtension(ext)
  66. }
  67. }
  68. if mimeType != "" {
  69. w.Header().Set("Content-Type", mimeType)
  70. }
  71. // if modified since
  72. if !entry.Attr.Mtime.IsZero() {
  73. w.Header().Set("Last-Modified", entry.Attr.Mtime.UTC().Format(http.TimeFormat))
  74. if r.Header.Get("If-Modified-Since") != "" {
  75. if t, parseError := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); parseError == nil {
  76. if t.After(entry.Attr.Mtime) {
  77. w.WriteHeader(http.StatusNotModified)
  78. return
  79. }
  80. }
  81. }
  82. }
  83. // set etag
  84. etag := filer2.ETagEntry(entry)
  85. if inm := r.Header.Get("If-None-Match"); inm == "\""+etag+"\"" {
  86. w.WriteHeader(http.StatusNotModified)
  87. return
  88. }
  89. setEtag(w, etag)
  90. if r.Method == "HEAD" {
  91. w.Header().Set("Content-Length", strconv.FormatInt(int64(filer2.TotalSize(entry.Chunks)), 10))
  92. return
  93. }
  94. filename := entry.Name()
  95. adjustHeadersAfterHEAD(w, r, filename)
  96. totalSize := int64(filer2.TotalSize(entry.Chunks))
  97. if rangeReq := r.Header.Get("Range"); rangeReq == "" {
  98. ext := filepath.Ext(filename)
  99. width, height, mode, shouldResize := shouldResizeImages(ext, r)
  100. if shouldResize {
  101. chunkedFileReader := filer2.NewChunkStreamReaderFromFiler(fs.filer.MasterClient, entry.Chunks)
  102. rs, _, _ := images.Resized(ext, chunkedFileReader, width, height, mode)
  103. io.Copy(w, rs)
  104. return
  105. }
  106. }
  107. processRangeRequest(r, w, totalSize, mimeType, func(writer io.Writer, offset int64, size int64) error {
  108. return filer2.StreamContent(fs.filer.MasterClient, writer, entry.Chunks, offset, size)
  109. })
  110. }