1- use std:: { str:: FromStr , sync:: Arc } ;
1+ use std:: { net :: SocketAddr , str:: FromStr , sync:: Arc } ;
22
33use axum:: {
4- extract:: Request ,
4+ body:: Body ,
5+ extract:: { ConnectInfo , Request } ,
56 http:: { HeaderValue , StatusCode } ,
67 middleware:: { from_fn, Next } ,
78 response:: { IntoResponse , Response } ,
@@ -12,6 +13,7 @@ mod address;
1213mod block;
1314mod cache;
1415pub mod common;
16+ mod debug;
1517mod fee;
1618mod governance;
1719mod loan;
@@ -105,24 +107,62 @@ pub async fn ocean_router(
105107 services : services. clone ( ) ,
106108 network : Network :: from_str ( & network) ?,
107109 } ) ;
110+ let main_router = Router :: new ( )
111+ . nest ( "/address/" , address:: router ( Arc :: clone ( & context) ) )
112+ . nest ( "/governance" , governance:: router ( Arc :: clone ( & context) ) )
113+ . nest ( "/loans" , loan:: router ( Arc :: clone ( & context) ) )
114+ . nest ( "/fee" , fee:: router ( Arc :: clone ( & context) ) )
115+ . nest ( "/masternodes" , masternode:: router ( Arc :: clone ( & context) ) )
116+ . nest ( "/oracles" , oracle:: router ( Arc :: clone ( & context) ) )
117+ . nest ( "/poolpairs" , pool_pair:: router ( Arc :: clone ( & context) ) )
118+ . nest ( "/prices" , prices:: router ( Arc :: clone ( & context) ) )
119+ . nest ( "/rawtx" , rawtx:: router ( Arc :: clone ( & context) ) )
120+ . nest ( "/stats" , stats:: router ( Arc :: clone ( & context) ) )
121+ . nest ( "/tokens" , tokens:: router ( Arc :: clone ( & context) ) )
122+ . nest ( "/transactions" , transactions:: router ( Arc :: clone ( & context) ) )
123+ . nest ( "/blocks" , block:: router ( Arc :: clone ( & context) ) )
124+ . fallback ( not_found) ;
108125
109- Ok ( Router :: new ( ) . nest (
110- format ! ( "/v0/{}" , context. network) . as_str ( ) ,
111- Router :: new ( )
112- . nest ( "/address/" , address:: router ( Arc :: clone ( & context) ) )
113- . nest ( "/governance" , governance:: router ( Arc :: clone ( & context) ) )
114- . nest ( "/loans" , loan:: router ( Arc :: clone ( & context) ) )
115- . nest ( "/fee" , fee:: router ( Arc :: clone ( & context) ) )
116- . nest ( "/masternodes" , masternode:: router ( Arc :: clone ( & context) ) )
117- . nest ( "/oracles" , oracle:: router ( Arc :: clone ( & context) ) )
118- . nest ( "/poolpairs" , pool_pair:: router ( Arc :: clone ( & context) ) )
119- . nest ( "/prices" , prices:: router ( Arc :: clone ( & context) ) )
120- . nest ( "/rawtx" , rawtx:: router ( Arc :: clone ( & context) ) )
121- . nest ( "/stats" , stats:: router ( Arc :: clone ( & context) ) )
122- . nest ( "/tokens" , tokens:: router ( Arc :: clone ( & context) ) )
123- . nest ( "/transactions" , transactions:: router ( Arc :: clone ( & context) ) )
124- . nest ( "/blocks" , block:: router ( Arc :: clone ( & context) ) )
125- . fallback ( not_found)
126- . layer ( from_fn ( cors) ) , // NOTE(canonbrother): the `layer()` calls work in reverse order, hence cors layer must be at bottom
127- ) )
126+ let debug_router = Router :: new ( )
127+ . nest ( "/debug" , debug:: router ( Arc :: clone ( & context) ) )
128+ . layer ( from_fn ( localhost_only) ) ;
129+
130+ Ok ( Router :: new ( )
131+ . nest (
132+ format ! ( "/v0/{}" , context. network) . as_str ( ) ,
133+ main_router. merge ( debug_router) ,
134+ )
135+ . layer ( from_fn ( cors) ) )
136+ }
137+
138+ async fn localhost_only (
139+ req : Request < Body > ,
140+ next : Next ,
141+ ) -> std:: result:: Result < Response , StatusCode > {
142+ let is_localhost = req
143+ . extensions ( )
144+ . get :: < ConnectInfo < SocketAddr > > ( )
145+ . map ( |connect_info| connect_info. ip ( ) . is_loopback ( ) )
146+ . unwrap_or_else ( || {
147+ req. headers ( )
148+ . get ( "X-Forwarded-For" )
149+ . and_then ( |addr| addr. to_str ( ) . ok ( ) )
150+ . map ( |addr| addr. split ( ',' ) . next ( ) . unwrap_or ( "" ) . trim ( ) == "127.0.0.1" )
151+ . or_else ( || {
152+ req. headers ( )
153+ . get ( "Host" )
154+ . and_then ( |host| host. to_str ( ) . ok ( ) )
155+ . map ( |host| {
156+ host. starts_with ( "localhost:" ) || host. starts_with ( "127.0.0.1:" )
157+ } )
158+ } )
159+ . unwrap_or ( false )
160+ } ) ;
161+
162+ if is_localhost {
163+ Ok ( next. run ( req) . await )
164+ } else {
165+ println ! ( "Access denied: Request is not from localhost" ) ;
166+ Err ( StatusCode :: FORBIDDEN )
167+ }
128168}
0 commit comments