fix download route sending headers too early, improve when file not found on download, other minor related changes
This commit is contained in:
parent
51d6f2dbf2
commit
4f2fe0b015
|
@ -23,7 +23,7 @@ func HandleFileNotFound(relPath string, fullPath string, w http.ResponseWriter)
|
||||||
//info, err := os.Lstat(fullPath)
|
//info, err := os.Lstat(fullPath)
|
||||||
//if err != nil {
|
//if err != nil {
|
||||||
// log.Errorf("HELPERS:HandleFileNotFound - os.Lstat failed: %s", err)
|
// log.Errorf("HELPERS:HandleFileNotFound - os.Lstat failed: %s", err)
|
||||||
// Return500Msg(w)
|
// Return500(w)
|
||||||
// return nil
|
// return nil
|
||||||
//}
|
//}
|
||||||
//if !config.FollowSymlinks && info.Mode()&os.ModeSymlink > 0 {
|
//if !config.FollowSymlinks && info.Mode()&os.ModeSymlink > 0 {
|
||||||
|
@ -35,14 +35,14 @@ func HandleFileNotFound(relPath string, fullPath string, w http.ResponseWriter)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
item, err := dc.CrawlNoRecursion(fullPath, nil)
|
item, err := dc.CrawlNoRecursion(fullPath, nil)
|
||||||
if err == nil && (os.IsNotExist(err) || item == nil) {
|
if err == nil && (os.IsNotExist(err) || item == nil) {
|
||||||
ReturnFake404Msg("path not found", w)
|
ReturnFake404Msg("file not found", w)
|
||||||
return nil
|
return nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
ReturnFake404Msg("path not found", w)
|
ReturnFake404Msg("file not found", w)
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("HELPERS:HandleFileNotFound:Crawl - Crawl failed: %s", err)
|
log.Errorf("HELPERS:HandleFileNotFound:Crawl - Crawl failed: %s", err)
|
||||||
Return500Msg(w)
|
Return500(w)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ func HandleFileNotFound(relPath string, fullPath string, w http.ResponseWriter)
|
||||||
item, found := sharedcache.Cache.Get(relPath)
|
item, found := sharedcache.Cache.Get(relPath)
|
||||||
if !found {
|
if !found {
|
||||||
// Assume that it doesn't exist.
|
// Assume that it doesn't exist.
|
||||||
ReturnFake404Msg("path not found", w)
|
ReturnFake404Msg("file not found", w)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,14 @@ func HandleRejectDuringInitialCrawl(w http.ResponseWriter) {
|
||||||
WriteErrorResponse(http.StatusServiceUnavailable, http.StatusServiceUnavailable, "initial file system crawl in progress", w)
|
WriteErrorResponse(http.StatusServiceUnavailable, http.StatusServiceUnavailable, "initial file system crawl in progress", w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Return500Msg(w http.ResponseWriter) {
|
func Return500(w http.ResponseWriter) {
|
||||||
WriteErrorResponse(http.StatusInternalServerError, http.StatusInternalServerError, "internal server error", w)
|
WriteErrorResponse(http.StatusInternalServerError, http.StatusInternalServerError, "internal server error", w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Return500Msg(msg string, w http.ResponseWriter) {
|
||||||
|
WriteErrorResponse(500, http.StatusInternalServerError, msg, w)
|
||||||
|
}
|
||||||
|
|
||||||
func Return403Msg(msg string, w http.ResponseWriter) {
|
func Return403Msg(msg string, w http.ResponseWriter) {
|
||||||
WriteErrorResponse(http.StatusForbidden, http.StatusForbidden, msg, w)
|
WriteErrorResponse(http.StatusForbidden, http.StatusForbidden, msg, w)
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,20 +66,20 @@ func ZipHandlerCompressMultiple(paths []string, w http.ResponseWriter, r *http.R
|
||||||
if !item.IsDir {
|
if !item.IsDir {
|
||||||
writer, err := zipWriter.Create(relPath)
|
writer, err := zipWriter.Create(relPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Return500Msg(w)
|
Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.Open(fullPath)
|
file, err := os.Open(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Return500Msg(w)
|
Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
_, err = io.Copy(writer, file)
|
_, err = io.Copy(writer, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Return500Msg(w)
|
Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -79,7 +79,7 @@ func APISearch(w http.ResponseWriter, r *http.Request) {
|
||||||
resp, err := elastic.SimpleQuery(queryString, excludeElements, queryFields)
|
resp, err := elastic.SimpleQuery(queryString, excludeElements, queryFields)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(`ROUTES:Search - Failed to perform Elasticsearch query "%s" - %s`, queryString, err)
|
log.Errorf(`ROUTES:Search - Failed to perform Elasticsearch query "%s" - %s`, queryString, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ func APISearch(w http.ResponseWriter, r *http.Request) {
|
||||||
err = json.NewDecoder(resp.Body).Decode(&respData)
|
err = json.NewDecoder(resp.Body).Decode(&respData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(`ROUTES:Search - Failed to parse Elasticsearch response for query "%s" - %s`, queryString, err)
|
log.Errorf(`ROUTES:Search - Failed to parse Elasticsearch response for query "%s" - %s`, queryString, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,24 @@ func APIDownload(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !item.IsDir {
|
if !item.IsDir {
|
||||||
|
var err error
|
||||||
|
// Open the file
|
||||||
|
openFile, err := os.Open(fullPath)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
sharedcache.Cache.Remove(relPath) // Remove item from the cache
|
||||||
|
helpers.ReturnFake404Msg("cache out of date, file missing from disk", w)
|
||||||
|
} else {
|
||||||
|
log.Errorf(`Failed to open file for download: "%s" - "%s"`, fullPath, err)
|
||||||
|
helpers.Return500Msg("internal server error accessing file", w)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer openFile.Close()
|
||||||
|
|
||||||
|
// =============================================================================================================
|
||||||
|
// Get the file info
|
||||||
|
|
||||||
// Only files can have inline disposition, zip archives cannot
|
// Only files can have inline disposition, zip archives cannot
|
||||||
// https://stackoverflow.com/a/57994289
|
// https://stackoverflow.com/a/57994289
|
||||||
contentDownload := r.URL.Query().Get("download")
|
contentDownload := r.URL.Query().Get("download")
|
||||||
|
@ -95,27 +113,24 @@ func APIDownload(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// Get the MIME type of the file
|
// Get the MIME type of the file
|
||||||
var mimeType string
|
var mimeType string
|
||||||
var err error
|
if item.MimeType == nil { // Only if the MIME type of this item has not been set yet
|
||||||
if item.MimeType == nil { // only if the MIME type of this item has not been set yet
|
|
||||||
_, mimeType, _, err = file.GetMimeType(fullPath, true)
|
_, mimeType, _, err = file.GetMimeType(fullPath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("ROUTES:Download - Error detecting MIME type: %v", err)
|
log.Errorf("ROUTES:Download - Error detecting MIME type: %v", err)
|
||||||
} else if mimeType != "" {
|
} else if mimeType != "" {
|
||||||
// GetMimeType() returns an empty string if it was a directory.
|
// GetMimeType() returns an empty string if it was a directory.
|
||||||
// Update the cacheitem's MIME in the sharedCache.
|
|
||||||
item.MimeType = &mimeType
|
item.MimeType = &mimeType
|
||||||
sharedcache.Cache.Add(relPath, item)
|
sharedcache.Cache.Add(relPath, item) // Update the cacheitem's MIME in the sharedCache.
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("ROUTES:Download - Failed to match a condition when checking a file's MIME - %s", fullPath)
|
log.Errorf("ROUTES:Download - Failed to match a condition when checking a file's MIME - %s", fullPath)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mimeType = *item.MimeType
|
mimeType = *item.MimeType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the encoding of this file
|
// Get the encoding of this file
|
||||||
var encoding string
|
encoding := "utf-8" // fall back to utf-8
|
||||||
encoding = "utf-8" // fall back to utf-8
|
|
||||||
if item.Encoding == nil || *item.Encoding == "" { // only if the encoding of this item has not been set yet
|
if item.Encoding == nil || *item.Encoding == "" { // only if the encoding of this item has not been set yet
|
||||||
encoding, err = file.DetectFileEncoding(fullPath)
|
encoding, err = file.DetectFileEncoding(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -128,6 +143,11 @@ func APIDownload(w http.ResponseWriter, r *http.Request) {
|
||||||
encoding = *item.Encoding
|
encoding = *item.Encoding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =============================================================================================================
|
||||||
|
// Send the file to the client.
|
||||||
|
// We are using `http.ServeContent()` since this allows us to catch and handle any missing files. `http.ServeFile()` returns
|
||||||
|
// the default 404 page if the file is missing from the disk.
|
||||||
|
|
||||||
if config.GetConfig().HTTPNoMimeSniffHeader {
|
if config.GetConfig().HTTPNoMimeSniffHeader {
|
||||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
mimeType = file.CastTextMimes(mimeType)
|
mimeType = file.CastTextMimes(mimeType)
|
||||||
|
@ -138,32 +158,18 @@ func APIDownload(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", mimeType+"; charset="+encoding)
|
w.Header().Set("Content-Type", mimeType+"; charset="+encoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================================================
|
|
||||||
// Send the file to the client.
|
|
||||||
// We are using `http.ServeContent()` since this allows us to catch and handle any missing files. `http.ServeFile()` returns
|
|
||||||
// the default 404 page if the file is missing from the disk.
|
|
||||||
|
|
||||||
// Open the file
|
|
||||||
openFile, err := os.Open(fullPath)
|
|
||||||
if err != nil {
|
|
||||||
sharedcache.Cache.Remove(relPath) // remove it from the cache
|
|
||||||
helpers.ReturnFake404Msg("file missing from disk, cache out of date", w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer openFile.Close()
|
|
||||||
|
|
||||||
// Get the file info
|
// Get the file info
|
||||||
fileInfo, err := openFile.Stat()
|
fileInfo, err := openFile.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(`ROUTES:Download - Failed to stat file "%s" - %s`, fullPath, err)
|
log.Errorf(`ROUTES:Download - Failed to stat file "%s" - %s`, fullPath, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the file exists, serve it
|
// If the file exists, serve it.
|
||||||
http.ServeContent(w, r, fileInfo.Name(), fileInfo.ModTime(), openFile)
|
http.ServeContent(w, r, fileInfo.Name(), fileInfo.ModTime(), openFile)
|
||||||
} else {
|
} else {
|
||||||
// Stream archive of the directory here
|
// Stream archive of the directory.
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.zip"`, item.Name))
|
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.zip"`, item.Name))
|
||||||
helpers.ZipHandlerCompress(fullPath, w, r)
|
helpers.ZipHandlerCompress(fullPath, w, r)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ func APIList(w http.ResponseWriter, r *http.Request) {
|
||||||
fileExists, mimeType, ext, err := file.GetMimeType(fullPath, true)
|
fileExists, mimeType, ext, err := file.GetMimeType(fullPath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("ROUTES:List - Error detecting MIME type: %v", err)
|
log.Warnf("ROUTES:List - Error detecting MIME type: %v", err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !fileExists {
|
if !fileExists {
|
||||||
|
|
|
@ -94,7 +94,7 @@ func APIThumbnail(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf(`ROUTES:Thumb - Error detecting MIME type for "%s". %v`, fullPath, err)
|
log.Warnf(`ROUTES:Thumb - Error detecting MIME type for "%s". %v`, fullPath, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Update the item's MIME in the cache.
|
// Update the item's MIME in the cache.
|
||||||
|
@ -112,7 +112,7 @@ func APIThumbnail(w http.ResponseWriter, r *http.Request) {
|
||||||
imageBytes, err := file.ConvertToPNG(fullPath, mimeType)
|
imageBytes, err := file.ConvertToPNG(fullPath, mimeType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf(`ROUTES:Thumb - Error converting "%s". %v`, fullPath, err)
|
log.Warnf(`ROUTES:Thumb - Error converting "%s". %v`, fullPath, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ func APIThumbnail(w http.ResponseWriter, r *http.Request) {
|
||||||
img, err = png.Decode(bytes.NewReader(imageBytes))
|
img, err = png.Decode(bytes.NewReader(imageBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf(`ROUTES:Thumb - Error decoding "%s". %v`, fullPath, err)
|
log.Warnf(`ROUTES:Thumb - Error decoding "%s". %v`, fullPath, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,14 +129,14 @@ func APIThumbnail(w http.ResponseWriter, r *http.Request) {
|
||||||
img, err = resizeImage(img, width, height, square, autoScale)
|
img, err = resizeImage(img, width, height, square, autoScale)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf(`ROUTES:Thumb - Error resizing "%s". %v`, fullPath, err)
|
log.Warnf(`ROUTES:Thumb - Error resizing "%s". %v`, fullPath, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := file.CompressPNGFile(img, pngQuality)
|
buf, err := file.CompressPNGFile(img, pngQuality)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf(`ROUTES:Thumb - Error compressing "%s". %v`, fullPath, err)
|
log.Warnf(`ROUTES:Thumb - Error compressing "%s". %v`, fullPath, err)
|
||||||
helpers.Return500Msg(w)
|
helpers.Return500(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue