@@ -6,34 +6,29 @@ use config::Config;
66use ohttp_relay:: SentinelTag ;
77use rand:: Rng ;
88use tokio_listener:: { Listener , SystemOptions , UserOptions } ;
9- use tower:: Service ;
9+ use tower:: { Service , ServiceExt } ;
1010use tracing:: info;
11- pub mod ohttp;
12-
13- use http_body_util:: combinators:: BoxBody ;
14- use hyper:: body:: Bytes ;
15- use hyper:: { Request , StatusCode } ;
16- use ohttp:: { OhttpGatewayConfig , OhttpGatewayLayer } ;
17- use tower:: { ServiceBuilder , ServiceExt } ;
1811
1912pub mod cli;
2013pub mod config;
14+ pub mod ohttp;
15+
16+ use crate :: ohttp:: OhttpGatewayConfig ;
2117
2218#[ derive( Clone ) ]
2319struct Services {
2420 directory : payjoin_directory:: Service < payjoin_directory:: FilesDb > ,
2521 relay : ohttp_relay:: Service ,
26- sentinel_tag : SentinelTag ,
22+ ohttp_config : OhttpGatewayConfig ,
2723}
2824
2925pub async fn serve ( config : Config ) -> anyhow:: Result < ( ) > {
3026 let sentinel_tag = generate_sentinel_tag ( ) ;
27+ let directory = init_directory ( & config, sentinel_tag) . await ?;
28+ let ohttp_config = OhttpGatewayConfig :: new ( directory. ohttp . clone ( ) , sentinel_tag) ;
3129
32- let services = Services {
33- directory : init_directory ( & config, sentinel_tag) . await ?,
34- relay : ohttp_relay:: Service :: new ( sentinel_tag) . await ,
35- sentinel_tag,
36- } ;
30+ let services =
31+ Services { directory, relay : ohttp_relay:: Service :: new ( sentinel_tag) . await , ohttp_config } ;
3732 let app = Router :: new ( ) . fallback ( route_request) . with_state ( services) ;
3833
3934 let listener =
@@ -61,12 +56,15 @@ pub async fn serve_manual_tls(
6156 use std:: net:: SocketAddr ;
6257
6358 let sentinel_tag = generate_sentinel_tag ( ) ;
59+ let directory = init_directory ( & config, sentinel_tag) . await ?;
60+ let ohttp_config = OhttpGatewayConfig :: new ( directory. ohttp . clone ( ) , sentinel_tag) ;
6461
6562 let services = Services {
66- directory : init_directory ( & config , sentinel_tag ) . await ? ,
63+ directory,
6764 relay : ohttp_relay:: Service :: new_with_roots ( root_store, sentinel_tag) . await ,
68- sentinel_tag ,
65+ ohttp_config ,
6966 } ;
67+
7068 let app = Router :: new ( ) . fallback ( route_request) . with_state ( services) ;
7169
7270 let addr: SocketAddr = config
@@ -134,63 +132,49 @@ async fn route_request(State(services): State<Services>, req: axum::extract::Req
134132 let mut relay = services. relay . clone ( ) ;
135133 match relay. call ( req) . await {
136134 Ok ( res) => res. into_response ( ) ,
137- Err ( e) => ( StatusCode :: BAD_GATEWAY , e. to_string ( ) ) . into_response ( ) ,
135+ Err ( e) => ( axum :: http :: StatusCode :: BAD_GATEWAY , e. to_string ( ) ) . into_response ( ) ,
138136 }
139137 } else {
140138 handle_directory_request ( services, req) . await
141139 }
142140}
143141
144142async fn handle_directory_request ( services : Services , req : axum:: extract:: Request ) -> Response {
145- let ohttp_server = services. directory . ohttp . clone ( ) ;
146-
147- let ohttp_config = OhttpGatewayConfig :: new ( ohttp_server, services. sentinel_tag ) ;
148-
149- let ( parts, body) = req. into_parts ( ) ;
150-
151- use http_body_util:: BodyExt as _;
152-
153- let body_bytes = body
154- . collect ( )
155- . await
156- . map_err ( |_| "Failed to collect body" )
157- . expect ( "Failed to collect body" )
158- . to_bytes ( ) ;
159-
160- let boxed_body = BoxBody :: new ( http_body_util:: Full :: new ( body_bytes) ) ;
161-
162- let hyper_req = Request :: from_parts ( parts, boxed_body) ;
163-
164- let directory_service = tower:: service_fn ( {
165- let directory = services. directory . clone ( ) ;
166- move |req : Request < BoxBody < Bytes , hyper:: Error > > | {
167- let mut dir = directory. clone ( ) ;
168- async move {
169- dir. call ( req) . await . map_err ( |e| {
170- Box :: new ( std:: io:: Error :: other ( e. to_string ( ) ) )
171- as Box < dyn std:: error:: Error + Send + Sync >
172- } )
173- }
174- }
175- } ) ;
176-
177- let mut service_with_ohttp = ServiceBuilder :: new ( )
178- . layer ( OhttpGatewayLayer :: new ( ohttp_config) )
179- . service ( directory_service)
180- . boxed_clone ( ) ;
181-
182- match service_with_ohttp. ready ( ) . await {
183- Ok ( ready_service) => match ready_service. call ( hyper_req) . await {
184- Ok ( response) => {
185- let ( parts, body) = response. into_parts ( ) ;
186- let axum_body = axum:: body:: Body :: new ( body) ;
187- Response :: from_parts ( parts, axum_body) . into_response ( )
188- }
143+ let is_ohttp_request = matches ! (
144+ ( req. method( ) , req. uri( ) . path( ) ) ,
145+ ( & Method :: POST , "/.well-known/ohttp-gateway" ) | ( & Method :: POST , "/" )
146+ ) ;
147+
148+ if is_ohttp_request {
149+ let app = Router :: new ( )
150+ . fallback ( directory_handler)
151+ . layer ( axum:: middleware:: from_fn_with_state (
152+ services. ohttp_config . clone ( ) ,
153+ crate :: ohttp:: ohttp_gateway,
154+ ) )
155+ . with_state ( services. directory . clone ( ) ) ;
156+
157+ match app. oneshot ( req) . await {
158+ Ok ( response) => response,
189159 Err ( e) =>
190- ( StatusCode :: INTERNAL_SERVER_ERROR , format ! ( "Service error: {}" , e) ) . into_response ( ) ,
191- } ,
160+ ( axum:: http:: StatusCode :: INTERNAL_SERVER_ERROR , format ! ( "Service error: {}" , e) )
161+ . into_response ( ) ,
162+ }
163+ } else {
164+ directory_handler ( State ( services. directory ) , req) . await
165+ }
166+ }
167+
168+ async fn directory_handler (
169+ State ( directory) : State < payjoin_directory:: Service < payjoin_directory:: FilesDb > > ,
170+ req : axum:: extract:: Request ,
171+ ) -> Response {
172+ let mut dir = directory. clone ( ) ;
173+ match dir. call ( req) . await {
174+ Ok ( response) => response. into_response ( ) ,
192175 Err ( e) =>
193- ( StatusCode :: INTERNAL_SERVER_ERROR , format ! ( "Service not ready: {}" , e) ) . into_response ( ) ,
176+ ( axum:: http:: StatusCode :: INTERNAL_SERVER_ERROR , format ! ( "Directory error: {}" , e) )
177+ . into_response ( ) ,
194178 }
195179}
196180
0 commit comments