Skip to content

Implement backend fetching for images. #4

@NicTanghe

Description

@NicTanghe

I swear this is not over-engineering

doing things like this allows us to later move the CDN behind the gateway so that there is access filtering on the content.

remarks

you need to add a server side leptos function

rough instructions

Steps to Implement Backend Fetching:

Modify the CDN URL Logic: Instead of directly using the CDN URL in the filter_gif function, you can modify the filter_gif function to fetch the image from the CDN server-side.

Create an Endpoint to Fetch the Image: You can create a new endpoint in your Axum server that will fetch the image from the internal CDN and return it to the client.

Update the Frontend to Use the New Endpoint: Instead of using the direct CDN URL, the frontend will request the image from the new server-side endpoint, which will internally fetch the image from the CDN.

Example of Backend Fetching in Axum

  1. Create a new endpoint in Axum to fetch the image:
use axum::{Router, routing::get, response::{IntoResponse, Response}};
use reqwest::Client;
use std::sync::Arc;
use tokio::sync::Mutex;

async fn fetch_image_from_cdn(client: Arc<Mutex<Client>>, image_path: String) -> impl IntoResponse {
    let client = client.lock().await;
    let url = format!("http://192.168.2.13:5434{}", image_path);

    match client.get(&url).send().await {
        Ok(response) => {
            if response.status().is_success() {
                let body = response.bytes().await.unwrap();
                Response::builder()
                    .header("Content-Type", response.headers().get("Content-Type").unwrap().to_str().unwrap())
                    .body(body)
                    .unwrap()
            } else {
                Response::builder().status(404).body("Image not found".into()).unwrap()
            }
        }
        Err(_) => Response::builder().status(500).body("Failed to fetch image".into()).unwrap(),
    }
}

pub async fn app() -> Router {
    let client = Arc::new(Mutex::new(Client::new()));

    Router::new()
        .route("/fetch_image/:category", get(move |path: axum::extract::Path<String>| {
            fetch_image_from_cdn(client.clone(), path.into_inner())
        }))
}
  1. Update the filter_gif function to use the new server-side endpoint:

In your Leptos component, update the filter_gif function to point to the new endpoint on your backend (instead of the CDN address directly):

let filter_gif = |category: &str| -> Option<String> {
    match category {
        "programming" => Some("/fetch_image/programming.gif".to_string()),
        "modelling" => Some("/fetch_image/programming.gif".to_string()),
        "lookdev" => Some("/fetch_image/programming.gif".to_string()),
        "compositing" => Some("/fetch_image/programming.gif".to_string()),
        "pipeline" => Some("/fetch_image/programming.gif".to_string()),
        "editing" => Some("/fetch_image/programming.gif".to_string()),
        _ => None,
    }
};
  1. Update the frontend to use the new endpoint:

Now, the frontend will request the image from the server-side endpoint /fetch_image/{category}, which will internally fetch the image from the CDN.
Advantages of This Approach:

No Need to Expose CDN to the Internet: The CDN remains internal, and only your server is responsible for fetching and serving the images.
Control Over Image Access: You can implement additional logic, such as caching or logging, to control how the images are served.
Simplified Frontend: The frontend only needs to request images from the backend, and you don't need to worry about the local network or public exposure of the CDN.

Considerations:

Performance: The server now has to handle fetching and serving the images, which could increase the load. You can mitigate this by caching the images server-side or using a CDN for the server-side as well.
Error Handling: Make sure to handle cases where the image isn't found or there are network issues fetching from the CDN.

Let me know if you'd like help with any part of the implementation!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions