@@ -9,18 +9,20 @@ use axum::extract::{Query, Request, State};
99use axum:: handler:: HandlerWithoutStateExt ;
1010use axum:: http:: Uri ;
1111use axum:: response:: IntoResponse ;
12- use axum:: routing:: get;
12+ use axum:: routing:: { get, post } ;
1313use axum:: Router ;
1414use clap:: Parser ;
15- use function_router:: { route_meta, Route , ServerApp , ServerAppProps } ;
15+ use function_router:: { route_meta, Route } ;
1616use futures:: stream:: { self , StreamExt } ;
1717use hyper:: body:: Incoming ;
1818use hyper_util:: rt:: TokioIo ;
1919use hyper_util:: server;
20+ use ssr_router:: { LinkedAuthor , LinkedPost , LinkedPostMeta , ServerApp , ServerAppProps } ;
2021use tokio:: net:: TcpListener ;
2122use tower:: Service ;
2223use tower_http:: services:: ServeDir ;
2324use yew:: platform:: Runtime ;
25+ use yew_link:: { linked_state_handler, Resolver , ResolverProp } ;
2426use yew_router:: prelude:: Routable ;
2527
2628// We use jemalloc as it produces better performance.
@@ -45,25 +47,36 @@ fn head_tags_for(path: &str) -> String {
4547 )
4648}
4749
50+ #[ derive( Clone ) ]
51+ struct AppState {
52+ index_html_before : String ,
53+ index_html_after : String ,
54+ resolver : ResolverProp ,
55+ }
56+
4857async fn render (
4958 url : Uri ,
5059 Query ( queries) : Query < HashMap < String , String > > ,
51- State ( ( index_html_before , index_html_after ) ) : State < ( String , String ) > ,
60+ State ( state ) : State < AppState > ,
5261) -> impl IntoResponse {
5362 let path = url. path ( ) . to_owned ( ) ;
5463
5564 // Inject route-specific <head> tags before </head>, outside of Yew rendering.
56- let before = index_html_before. replace ( "</head>" , & format ! ( "{}</head>" , head_tags_for( & path) ) ) ;
65+ let before = state
66+ . index_html_before
67+ . replace ( "</head>" , & format ! ( "{}</head>" , head_tags_for( & path) ) ) ;
68+ let resolver = state. resolver . clone ( ) ;
5769
5870 let renderer = yew:: ServerRenderer :: < ServerApp > :: with_props ( move || ServerAppProps {
5971 url : path. into ( ) ,
6072 queries,
73+ resolver,
6174 } ) ;
6275
6376 Body :: from_stream (
6477 stream:: once ( async move { before } )
6578 . chain ( renderer. render_stream ( ) )
66- . chain ( stream:: once ( async move { index_html_after } ) )
79+ . chain ( stream:: once ( async move { state . index_html_after } ) )
6780 . map ( Result :: < _ , Infallible > :: Ok ) ,
6881 )
6982}
@@ -93,33 +106,43 @@ where
93106#[ tokio:: main]
94107async fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error + Send + Sync > > {
95108 let exec = Executor :: default ( ) ;
96-
97109 env_logger:: init ( ) ;
98-
99110 let opts = Opt :: parse ( ) ;
100111
112+ let resolver_prop: ResolverProp = Resolver :: new ( )
113+ . register_linked :: < LinkedPost > ( ( ) )
114+ . register_linked :: < LinkedAuthor > ( ( ) )
115+ . register_linked :: < LinkedPostMeta > ( ( ) )
116+ . into ( ) ;
117+ let arc_resolver = resolver_prop. 0 . clone ( ) ;
118+
101119 let index_html_s = tokio:: fs:: read_to_string ( opts. dir . join ( "index.html" ) )
102120 . await
103121 . expect ( "failed to read index.html" ) ;
104122
105123 let ( index_html_before, index_html_after) = index_html_s. split_once ( "<body>" ) . unwrap ( ) ;
106124 let mut index_html_before = index_html_before. to_owned ( ) ;
107125 index_html_before. push_str ( "<body>" ) ;
108-
109126 let index_html_after = index_html_after. to_owned ( ) ;
110127
111- let app = Router :: new ( ) . fallback_service (
112- ServeDir :: new ( opts. dir )
113- . append_index_html_on_directories ( false )
114- . fallback (
115- get ( render)
116- . with_state ( ( index_html_before. clone ( ) , index_html_after. clone ( ) ) )
117- . into_service ( ) ,
118- ) ,
119- ) ;
128+ let app_state = AppState {
129+ index_html_before,
130+ index_html_after,
131+ resolver : resolver_prop,
132+ } ;
133+
134+ let app = Router :: new ( )
135+ . route (
136+ "/api/link" ,
137+ post ( linked_state_handler) . with_state ( arc_resolver) ,
138+ )
139+ . fallback_service (
140+ ServeDir :: new ( opts. dir )
141+ . append_index_html_on_directories ( false )
142+ . fallback ( get ( render) . with_state ( app_state) . into_service ( ) ) ,
143+ ) ;
120144
121145 let addr: SocketAddr = ( [ 0 , 0 , 0 , 0 ] , 8080 ) . into ( ) ;
122-
123146 println ! ( "You can view the website at: http://localhost:8080/" ) ;
124147
125148 let listener = TcpListener :: bind ( addr) . await ?;
0 commit comments