mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2024-11-23 12:40:19 +01:00
Merge pull request #234 from dopessoa/ISSUE-229
Add X-Remaining-Downloads and X-Remaining-Days headers to HEAD and GET responses
This commit is contained in:
commit
14c48cb4d8
1 changed files with 37 additions and 15 deletions
|
@ -564,6 +564,14 @@ func getURL(r *http.Request) *url.URL {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calcRemainingLimits(metadata Metadata) (int, int) {
|
||||||
|
remainingDownloads := metadata.MaxDownloads - metadata.Downloads
|
||||||
|
timeDifference := metadata.MaxDate.Sub(time.Now())
|
||||||
|
remainingDays := int(timeDifference.Hours()/24) + 1
|
||||||
|
|
||||||
|
return remainingDownloads, remainingDays
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) Lock(token, filename string) error {
|
func (s *Server) Lock(token, filename string) error {
|
||||||
key := path.Join(token, filename)
|
key := path.Join(token, filename)
|
||||||
|
|
||||||
|
@ -583,7 +591,7 @@ func (s *Server) Unlock(token, filename string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CheckMetadata(token, filename string) error {
|
func (s *Server) CheckMetadata(token, filename string, increaseDownload bool) (Metadata, error) {
|
||||||
s.Lock(token, filename)
|
s.Lock(token, filename)
|
||||||
defer s.Unlock(token, filename)
|
defer s.Unlock(token, filename)
|
||||||
|
|
||||||
|
@ -591,34 +599,36 @@ func (s *Server) CheckMetadata(token, filename string) error {
|
||||||
|
|
||||||
r, _, _, err := s.storage.Get(token, fmt.Sprintf("%s.metadata", filename))
|
r, _, _, err := s.storage.Get(token, fmt.Sprintf("%s.metadata", filename))
|
||||||
if s.storage.IsNotExist(err) {
|
if s.storage.IsNotExist(err) {
|
||||||
return nil
|
return metadata, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
return metadata, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
if err := json.NewDecoder(r).Decode(&metadata); err != nil {
|
if err := json.NewDecoder(r).Decode(&metadata); err != nil {
|
||||||
return err
|
return metadata, err
|
||||||
} else if metadata.Downloads >= metadata.MaxDownloads {
|
} else if metadata.Downloads >= metadata.MaxDownloads {
|
||||||
return errors.New("MaxDownloads expired.")
|
return metadata, errors.New("MaxDownloads expired.")
|
||||||
} else if time.Now().After(metadata.MaxDate) {
|
} else if time.Now().After(metadata.MaxDate) {
|
||||||
return errors.New("MaxDate expired.")
|
return metadata, errors.New("MaxDate expired.")
|
||||||
} else {
|
} else {
|
||||||
// todo(nl5887): mutex?
|
// todo(nl5887): mutex?
|
||||||
|
|
||||||
// update number of downloads
|
// update number of downloads
|
||||||
metadata.Downloads++
|
if increaseDownload {
|
||||||
|
metadata.Downloads++
|
||||||
|
}
|
||||||
|
|
||||||
buffer := &bytes.Buffer{}
|
buffer := &bytes.Buffer{}
|
||||||
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
|
if err := json.NewEncoder(buffer).Encode(metadata); err != nil {
|
||||||
return errors.New("Could not encode metadata")
|
return metadata, errors.New("Could not encode metadata")
|
||||||
} else if err := s.storage.Put(token, fmt.Sprintf("%s.metadata", filename), buffer, "text/json", uint64(buffer.Len())); err != nil {
|
} else if err := s.storage.Put(token, fmt.Sprintf("%s.metadata", filename), buffer, "text/json", uint64(buffer.Len())); err != nil {
|
||||||
return errors.New("Could not save metadata")
|
return metadata, errors.New("Could not save metadata")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return metadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CheckDeletionToken(deletionToken, token, filename string) error {
|
func (s *Server) CheckDeletionToken(deletionToken, token, filename string) error {
|
||||||
|
@ -688,7 +698,7 @@ func (s *Server) zipHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
token := strings.Split(key, "/")[0]
|
token := strings.Split(key, "/")[0]
|
||||||
filename := sanitize(strings.Split(key, "/")[1])
|
filename := sanitize(strings.Split(key, "/")[1])
|
||||||
|
|
||||||
if err := s.CheckMetadata(token, filename); err != nil {
|
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
log.Printf("Error metadata: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -760,7 +770,7 @@ func (s *Server) tarGzHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
token := strings.Split(key, "/")[0]
|
token := strings.Split(key, "/")[0]
|
||||||
filename := sanitize(strings.Split(key, "/")[1])
|
filename := sanitize(strings.Split(key, "/")[1])
|
||||||
|
|
||||||
if err := s.CheckMetadata(token, filename); err != nil {
|
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
log.Printf("Error metadata: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -819,7 +829,7 @@ func (s *Server) tarHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
token := strings.Split(key, "/")[0]
|
token := strings.Split(key, "/")[0]
|
||||||
filename := strings.Split(key, "/")[1]
|
filename := strings.Split(key, "/")[1]
|
||||||
|
|
||||||
if err := s.CheckMetadata(token, filename); err != nil {
|
if _, err := s.CheckMetadata(token, filename, true); err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
log.Printf("Error metadata: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -864,7 +874,9 @@ func (s *Server) headHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
token := vars["token"]
|
token := vars["token"]
|
||||||
filename := vars["filename"]
|
filename := vars["filename"]
|
||||||
|
|
||||||
if err := s.CheckMetadata(token, filename); err != nil {
|
metadata, err := s.CheckMetadata(token, filename, false)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
log.Printf("Error metadata: %s", err.Error())
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
|
@ -880,9 +892,13 @@ func (s *Server) headHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remainingDownloads, remainingDays := calcRemainingLimits(metadata)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
|
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
|
||||||
w.Header().Set("Connection", "close")
|
w.Header().Set("Connection", "close")
|
||||||
|
w.Header().Set("X-Remaining-Downloads", strconv.Itoa(remainingDownloads))
|
||||||
|
w.Header().Set("X-Remaining-Days", strconv.Itoa(remainingDays))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -892,7 +908,9 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
token := vars["token"]
|
token := vars["token"]
|
||||||
filename := vars["filename"]
|
filename := vars["filename"]
|
||||||
|
|
||||||
if err := s.CheckMetadata(token, filename); err != nil {
|
metadata, err := s.CheckMetadata(token, filename, true)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
log.Printf("Error metadata: %s", err.Error())
|
log.Printf("Error metadata: %s", err.Error())
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
|
@ -918,10 +936,14 @@ func (s *Server) getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
disposition = "attachment"
|
disposition = "attachment"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remainingDownloads, remainingDays := calcRemainingLimits(metadata)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
|
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf("%s; filename=\"%s\"", disposition, filename))
|
w.Header().Set("Content-Disposition", fmt.Sprintf("%s; filename=\"%s\"", disposition, filename))
|
||||||
w.Header().Set("Connection", "keep-alive")
|
w.Header().Set("Connection", "keep-alive")
|
||||||
|
w.Header().Set("X-Remaining-Downloads", strconv.Itoa(remainingDownloads))
|
||||||
|
w.Header().Set("X-Remaining-Days", strconv.Itoa(remainingDays))
|
||||||
|
|
||||||
if w.Header().Get("Range") == "" {
|
if w.Header().Get("Range") == "" {
|
||||||
if _, err = io.Copy(w, reader); err != nil {
|
if _, err = io.Copy(w, reader); err != nil {
|
||||||
|
|
Loading…
Reference in a new issue