Merge pull request 'Setup routing for image and audio assets based on environment variables' (#107) from 35-make-asset-paths-configurable into main
Reviewed-on: LibreTunes/LibreTunes#107 Reviewed-by: Ethan Girouard <ethan@girouard.com>
This commit is contained in:
commit
3cfcacc9ba
@ -15,3 +15,6 @@ DATABASE_URL=postgresql://libretunes:password@localhost:5432/libretunes
|
|||||||
# POSTGRES_HOST=localhost
|
# POSTGRES_HOST=localhost
|
||||||
# POSTGRES_PORT=5432
|
# POSTGRES_PORT=5432
|
||||||
# POSTGRES_DB=libretunes
|
# POSTGRES_DB=libretunes
|
||||||
|
|
||||||
|
LIBRETUNES_AUDIO_PATH=assets/audio
|
||||||
|
LIBRETUNES_IMAGE_PATH=assets/images
|
||||||
|
@ -13,8 +13,11 @@ services:
|
|||||||
POSTGRES_USER: ${POSTGRES_USER}
|
POSTGRES_USER: ${POSTGRES_USER}
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
POSTGRES_DB: ${POSTGRES_DB}
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
LIBRETUNES_AUDIO_PATH: /assets/audio
|
||||||
|
LIBRETUNES_IMAGE_PATH: /assets/images
|
||||||
volumes:
|
volumes:
|
||||||
- libretunes-audio:/site/audio
|
- libretunes-audio:/assets/audio
|
||||||
|
- libretunes-images:/assets/images
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
- postgres
|
- postgres
|
||||||
|
@ -12,6 +12,7 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
|||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub async fn file_and_error_handler(uri: Uri, State(options): State<LeptosOptions>, req: Request<Body>) -> AxumResponse {
|
pub async fn file_and_error_handler(uri: Uri, State(options): State<LeptosOptions>, req: Request<Body>) -> AxumResponse {
|
||||||
let root = options.site_root.clone();
|
let root = options.site_root.clone();
|
||||||
@ -27,6 +28,7 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
|||||||
|
|
||||||
pub async fn get_static_file(uri: Uri, root: &str) -> Result<Response<Body>, (StatusCode, String)> {
|
pub async fn get_static_file(uri: Uri, root: &str) -> Result<Response<Body>, (StatusCode, String)> {
|
||||||
let req = Request::builder().uri(uri.clone()).body(Body::empty()).unwrap();
|
let req = Request::builder().uri(uri.clone()).body(Body::empty()).unwrap();
|
||||||
|
|
||||||
// `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot`
|
// `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot`
|
||||||
// This path is relative to the cargo root
|
// This path is relative to the cargo root
|
||||||
match ServeDir::new(root).oneshot(req).await.ok() {
|
match ServeDir::new(root).oneshot(req).await.ok() {
|
||||||
@ -37,4 +39,32 @@ cfg_if! { if #[cfg(feature = "ssr")] {
|
|||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum AssetType {
|
||||||
|
Audio,
|
||||||
|
Image,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_asset_file(filename: String, asset_type: AssetType) -> Result<Response<Body>, (StatusCode, String)> {
|
||||||
|
const DEFAULT_AUDIO_PATH: &str = "assets/audio";
|
||||||
|
const DEFAULT_IMAGE_PATH: &str = "assets/images";
|
||||||
|
|
||||||
|
let root = match asset_type {
|
||||||
|
AssetType::Audio => std::env::var("LIBRETUNES_AUDIO_PATH").unwrap_or(DEFAULT_AUDIO_PATH.to_string()),
|
||||||
|
AssetType::Image => std::env::var("LIBRETUNES_IMAGE_PATH").unwrap_or(DEFAULT_IMAGE_PATH.to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a Uri from the filename
|
||||||
|
// ServeDir expects a leading `/`
|
||||||
|
let uri = Uri::from_str(format!("/{}", filename).as_str());
|
||||||
|
|
||||||
|
match uri {
|
||||||
|
Ok(uri) => get_static_file(uri, root.as_str()).await,
|
||||||
|
Err(_) => Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("Attempted to serve an invalid file"),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
@ -14,11 +14,11 @@ extern crate diesel_migrations;
|
|||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
use axum::{routing::get, Router};
|
use axum::{routing::get, Router, extract::Path};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||||
use libretunes::app::*;
|
use libretunes::app::*;
|
||||||
use libretunes::fileserv::{file_and_error_handler, get_static_file};
|
use libretunes::fileserv::{file_and_error_handler, get_asset_file, get_static_file, AssetType};
|
||||||
use axum_login::tower_sessions::SessionManagerLayer;
|
use axum_login::tower_sessions::SessionManagerLayer;
|
||||||
use tower_sessions_redis_store::{fred::prelude::*, RedisStore};
|
use tower_sessions_redis_store::{fred::prelude::*, RedisStore};
|
||||||
use axum_login::AuthManagerLayerBuilder;
|
use axum_login::AuthManagerLayerBuilder;
|
||||||
@ -60,6 +60,8 @@ async fn main() {
|
|||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.leptos_routes(&leptos_options, routes, App)
|
.leptos_routes(&leptos_options, routes, App)
|
||||||
|
.route("/assets/audio/:song", get(|Path(song) : Path<String>| get_asset_file(song, AssetType::Audio)))
|
||||||
|
.route("/assets/images/:image", get(|Path(image) : Path<String>| get_asset_file(image, AssetType::Image)))
|
||||||
.route("/assets/*uri", get(|uri| get_static_file(uri, "")))
|
.route("/assets/*uri", get(|uri| get_static_file(uri, "")))
|
||||||
.layer(auth_layer)
|
.layer(auth_layer)
|
||||||
.fallback(file_and_error_handler)
|
.fallback(file_and_error_handler)
|
||||||
|
@ -49,7 +49,6 @@ impl TryInto<Song> for SongData {
|
|||||||
track: self.track,
|
track: self.track,
|
||||||
duration: self.duration,
|
duration: self.duration,
|
||||||
release_date: self.release_date,
|
release_date: self.release_date,
|
||||||
// TODO https://gitlab.mregirouard.com/libretunes/libretunes/-/issues/35
|
|
||||||
storage_path: self.song_path,
|
storage_path: self.song_path,
|
||||||
|
|
||||||
// Note that if the source of the image_path was the album, the image_path
|
// Note that if the source of the image_path was the album, the image_path
|
||||||
|
Loading…
x
Reference in New Issue
Block a user