feat: add From for RequestParts into Parts for Axum and add an option to ge… (#931)

This commit is contained in:
Ben Wishovich 2023-04-24 17:08:28 -07:00 committed by GitHub
parent fa2e2248d3
commit 6c3381ce52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 9 deletions

View file

@ -1,12 +1,15 @@
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
#[tokio::main] #[tokio::main]
async fn main(){ async fn main() {
use axum::{
extract::{Extension, Path},
routing::{get, post},
Router,
};
use leptos::*; use leptos::*;
use leptos_axum::{generate_route_list, LeptosRoutes}; use leptos_axum::{generate_route_list, LeptosRoutes};
use axum::{extract::{Extension, Path}, Router, routing::{get, post}}; use ssr_modes_axum::{app::*, fallback::file_and_error_handler};
use std::sync::Arc; use std::sync::Arc;
use ssr_modes_axum::fallback::file_and_error_handler;
use ssr_modes_axum::app::*;
let conf = get_configuration(None).await.unwrap(); let conf = get_configuration(None).await.unwrap();
let addr = conf.leptos_options.site_addr; let addr = conf.leptos_options.site_addr;
@ -19,7 +22,11 @@ async fn main(){
let app = Router::new() let app = Router::new()
.route("/api/*fn_name", post(leptos_axum::handle_server_fns)) .route("/api/*fn_name", post(leptos_axum::handle_server_fns))
.leptos_routes(leptos_options.clone(), routes, |cx| view! { cx, <App/> }) .leptos_routes(
leptos_options.clone(),
routes,
|cx| view! { cx, <App/> },
)
.fallback(file_and_error_handler) .fallback(file_and_error_handler)
.layer(Extension(Arc::new(leptos_options))); .layer(Extension(Arc::new(leptos_options)));

View file

@ -905,6 +905,20 @@ async fn render_app_async_helper(
pub fn generate_route_list<IV>( pub fn generate_route_list<IV>(
app_fn: impl FnOnce(leptos::Scope) -> IV + 'static, app_fn: impl FnOnce(leptos::Scope) -> IV + 'static,
) -> Vec<RouteListing> ) -> Vec<RouteListing>
where
IV: IntoView + 'static,
{
generate_route_list_with_exclusions(app_fn, None)
}
/// Generates a list of all routes defined in Leptos's Router in your app. We can then use this to automatically
/// create routes in Actix's App without having to use wildcard matching or fallbacks. Takes in your root app Element
/// as an argument so it can walk you app tree. This version is tailored to generated Actix compatible paths. Adding excluded_routes
/// to this function will stop `.leptos_routes()` from generating a route for it, allowing a custom handler. These need to be in Actix path format
pub fn generate_route_list_with_exclusions<IV>(
app_fn: impl FnOnce(leptos::Scope) -> IV + 'static,
excluded_routes: Option<Vec<String>>,
) -> Vec<RouteListing>
where where
IV: IntoView + 'static, IV: IntoView + 'static,
{ {
@ -932,7 +946,7 @@ where
// Match `:some_word` but only capture `some_word` in the groups to replace with `{some_word}` // Match `:some_word` but only capture `some_word` in the groups to replace with `{some_word}`
let capture_re = Regex::new(r":((?:[^.,/]+)+)[^/]?").unwrap(); let capture_re = Regex::new(r":((?:[^.,/]+)+)[^/]?").unwrap();
let routes = routes let mut routes = routes
.into_iter() .into_iter()
.map(|listing| { .map(|listing| {
let path = wildcard_re let path = wildcard_re
@ -946,6 +960,10 @@ where
if routes.is_empty() { if routes.is_empty() {
vec![RouteListing::new("/", Default::default(), [Method::Get])] vec![RouteListing::new("/", Default::default(), [Method::Get])]
} else { } else {
// Routes to exclude from auto generation
if let Some(excluded_routes) = excluded_routes {
routes.retain(|p| !excluded_routes.iter().any(|e| e == p.path()))
}
routes routes
} }
} }

View file

@ -19,7 +19,10 @@ use futures::{
channel::mpsc::{Receiver, Sender}, channel::mpsc::{Receiver, Sender},
Future, SinkExt, Stream, StreamExt, Future, SinkExt, Stream, StreamExt,
}; };
use http::{header, method::Method, uri::Uri, version::Version, Response}; use http::{
header, method::Method, request::Parts, uri::Uri, version::Version,
Response,
};
use hyper::body; use hyper::body;
use leptos::{ use leptos::{
leptos_server::{server_fn_by_path, Payload}, leptos_server::{server_fn_by_path, Payload},
@ -46,6 +49,21 @@ pub struct RequestParts {
pub headers: HeaderMap<HeaderValue>, pub headers: HeaderMap<HeaderValue>,
pub body: Bytes, pub body: Bytes,
} }
/// Convert http::Parts to RequestParts(and vice versa). Body and Extensions will
/// be lost in the conversion
impl From<Parts> for RequestParts {
fn from(parts: Parts) -> Self {
Self {
version: parts.version,
method: parts.method,
uri: parts.uri,
headers: parts.headers,
body: Bytes::default(),
}
}
}
/// This struct lets you define headers and override the status of the Response from an Element or a Server Function /// This struct lets you define headers and override the status of the Response from an Element or a Server Function
/// Typically contained inside of a ResponseOptions. Setting this is useful for cookies and custom responses. /// Typically contained inside of a ResponseOptions. Setting this is useful for cookies and custom responses.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -1003,6 +1021,21 @@ where
pub async fn generate_route_list<IV>( pub async fn generate_route_list<IV>(
app_fn: impl FnOnce(Scope) -> IV + 'static, app_fn: impl FnOnce(Scope) -> IV + 'static,
) -> Vec<RouteListing> ) -> Vec<RouteListing>
where
IV: IntoView + 'static,
{
generate_route_list_with_exclusions(app_fn, None).await
}
/// Generates a list of all routes defined in Leptos's Router in your app. We can then use this to automatically
/// create routes in Axum's Router without having to use wildcard matching or fallbacks. Takes in your root app Element
/// as an argument so it can walk you app tree. This version is tailored to generate Axum compatible paths. Adding excluded_routes
/// to this function will stop `.leptos_routes()` from generating a route for it, allowing a custom handler. These need to be in Axum path format
#[tracing::instrument(level = "trace", fields(error), skip_all)]
pub async fn generate_route_list_with_exclusions<IV>(
app_fn: impl FnOnce(Scope) -> IV + 'static,
excluded_routes: Option<Vec<String>>,
) -> Vec<RouteListing>
where where
IV: IntoView + 'static, IV: IntoView + 'static,
{ {
@ -1029,7 +1062,7 @@ where
let routes = routes.0.read().to_owned(); let routes = routes.0.read().to_owned();
// Axum's Router defines Root routes as "/" not "" // Axum's Router defines Root routes as "/" not ""
let routes = routes let mut routes = routes
.into_iter() .into_iter()
.map(|listing| { .map(|listing| {
let path = listing.path(); let path = listing.path();
@ -1052,6 +1085,10 @@ where
[leptos_router::Method::Get], [leptos_router::Method::Get],
)] )]
} else { } else {
// Routes to exclude from auto generation
if let Some(excluded_routes) = excluded_routes {
routes.retain(|p| !excluded_routes.iter().any(|e| e == p.path()))
}
routes routes
} }
} }

View file

@ -947,6 +947,19 @@ where
pub async fn generate_route_list<IV>( pub async fn generate_route_list<IV>(
app_fn: impl FnOnce(Scope) -> IV + 'static, app_fn: impl FnOnce(Scope) -> IV + 'static,
) -> Vec<RouteListing> ) -> Vec<RouteListing>
where
IV: IntoView + 'static,
{
generate_route_list_with_exclusions(app_fn, None).await
}
/// Generates a list of all routes defined in Leptos's Router in your app. We can then use this to automatically
/// create routes in Viz's Router without having to use wildcard matching or fallbacks. Takes in your root app Element
/// as an argument so it can walk you app tree. This version is tailored to generate Viz compatible paths.
pub async fn generate_route_list_with_exclusions<IV>(
app_fn: impl FnOnce(Scope) -> IV + 'static,
excluded_routes: Option<Vec<String>>,
) -> Vec<RouteListing>
where where
IV: IntoView + 'static, IV: IntoView + 'static,
{ {
@ -973,7 +986,7 @@ where
let routes = routes.0.read().to_owned(); let routes = routes.0.read().to_owned();
// Viz's Router defines Root routes as "/" not "" // Viz's Router defines Root routes as "/" not ""
let routes = routes let mut routes = routes
.into_iter() .into_iter()
.map(|listing| { .map(|listing| {
let path = listing.path(); let path = listing.path();
@ -996,6 +1009,9 @@ where
[leptos_router::Method::Get], [leptos_router::Method::Get],
)] )]
} else { } else {
if let Some(excluded_routes) = excluded_routes {
routes.retain(|p| !excluded_routes.iter().any(|e| e == p.path()))
}
routes routes
} }
} }