2020-02-09 14:21:53 +01:00
package routes
import (
2020-02-21 12:05:28 +01:00
"log"
2020-02-09 14:21:53 +01:00
"net/http"
"os"
2020-02-23 12:43:45 +01:00
"path"
"strconv"
2020-02-09 14:21:53 +01:00
2020-02-21 16:50:50 +01:00
"github.com/gorilla/mux"
2020-11-23 19:39:44 +01:00
"gorm.io/gorm"
2020-02-21 16:50:50 +01:00
2020-02-09 14:21:53 +01:00
"github.com/viktorstrate/photoview/api/graphql/models"
2020-02-23 12:43:45 +01:00
"github.com/viktorstrate/photoview/api/scanner"
2020-02-09 14:21:53 +01:00
)
2020-11-23 19:39:44 +01:00
func RegisterPhotoRoutes ( db * gorm . DB , router * mux . Router ) {
2020-02-21 16:50:50 +01:00
router . HandleFunc ( "/{name}" , func ( w http . ResponseWriter , r * http . Request ) {
2020-11-26 20:48:04 +01:00
mediaName := mux . Vars ( r ) [ "name" ]
2020-02-09 14:21:53 +01:00
2020-11-26 20:48:04 +01:00
var mediaURL models . MediaURL
result := db . Model ( & models . MediaURL { } ) . Select ( "media_urls.*" ) . Where ( "media_url.media_name = ?" , mediaName ) . Joins ( "JOIN media ON media_urls.media_id = media.id" ) . Scan ( & mediaURL )
if err := result . Error ; err != nil {
2020-02-09 14:21:53 +01:00
w . WriteHeader ( http . StatusNotFound )
w . Write ( [ ] byte ( "404" ) )
return
}
2020-11-26 20:48:04 +01:00
media := & mediaURL . Media
2020-02-23 18:00:08 +01:00
2020-07-12 18:52:48 +02:00
if success , response , status , err := authenticateMedia ( media , db , r ) ; ! success {
2020-02-21 12:05:28 +01:00
if err != nil {
2020-07-12 18:52:48 +02:00
log . Printf ( "WARN: error authenticating photo: %s\n" , err )
2020-02-21 12:05:28 +01:00
}
2020-07-12 18:52:48 +02:00
w . WriteHeader ( status )
w . Write ( [ ] byte ( response ) )
return
2020-02-20 17:31:41 +01:00
}
2020-02-23 18:00:08 +01:00
var cachedPath string
2020-02-09 14:21:53 +01:00
2020-11-26 20:48:04 +01:00
if mediaURL . Purpose == models . PhotoThumbnail || mediaURL . Purpose == models . PhotoHighRes || mediaURL . Purpose == models . VideoThumbnail {
cachedPath = path . Join ( scanner . PhotoCache ( ) , strconv . Itoa ( int ( media . AlbumID ) ) , strconv . Itoa ( int ( mediaURL . MediaID ) ) , mediaURL . MediaName )
} else if mediaURL . Purpose == models . MediaOriginal {
2020-07-10 14:26:19 +02:00
cachedPath = media . Path
2020-07-11 15:57:58 +02:00
} else {
2020-11-26 20:48:04 +01:00
log . Printf ( "ERROR: Can not handle media_purpose for photo: %s\n" , mediaURL . Purpose )
2020-07-11 15:57:58 +02:00
w . WriteHeader ( http . StatusInternalServerError )
w . Write ( [ ] byte ( "internal server error" ) )
return
2020-02-23 18:00:08 +01:00
}
2020-11-26 20:48:04 +01:00
if _ , err := os . Stat ( cachedPath ) ; os . IsNotExist ( ( err ) ) {
err := db . Transaction ( func ( tx * gorm . DB ) error {
if _ , err = scanner . ProcessMedia ( tx , media ) ; err != nil {
log . Printf ( "ERROR: processing image not found in cache: %s\n" , err )
return err
}
2020-11-16 12:40:06 +01:00
2020-11-26 20:48:04 +01:00
if _ , err = os . Stat ( cachedPath ) ; err != nil {
log . Printf ( "ERROR: after reprocessing image not found in cache: %s\n" , err )
return err
}
return nil
} )
2020-11-16 12:40:06 +01:00
if err != nil {
w . WriteHeader ( http . StatusInternalServerError )
w . Write ( [ ] byte ( "internal server error" ) )
return
2020-02-09 14:21:53 +01:00
}
}
2020-09-30 14:08:30 +02:00
// Allow caching the resource for 1 day
w . Header ( ) . Set ( "Cache-Control" , "private, max-age=86400, immutable" )
2020-11-16 12:40:06 +01:00
http . ServeFile ( w , r , cachedPath )
2020-02-09 14:21:53 +01:00
} )
}