@@ -40,13 +40,15 @@ use ldk_server_protos::endpoints::{
4040 BOLT11_RECEIVE_VIA_JIT_CHANNEL_PATH , BOLT11_SEND_PATH , BOLT12_RECEIVE_PATH , BOLT12_SEND_PATH ,
4141 CLOSE_CHANNEL_PATH , CONNECT_PEER_PATH , DECODE_INVOICE_PATH , DECODE_OFFER_PATH ,
4242 DISCONNECT_PEER_PATH , EXPORT_PATHFINDING_SCORES_PATH , FORCE_CLOSE_CHANNEL_PATH ,
43- GET_BALANCES_PATH , GET_NODE_INFO_PATH , GET_PAYMENT_DETAILS_PATH , GRAPH_GET_CHANNEL_PATH ,
44- GRAPH_GET_NODE_PATH , GRAPH_LIST_CHANNELS_PATH , GRAPH_LIST_NODES_PATH , LIST_CHANNELS_PATH ,
45- LIST_FORWARDED_PAYMENTS_PATH , LIST_PAYMENTS_PATH , LIST_PEERS_PATH , ONCHAIN_RECEIVE_PATH ,
46- ONCHAIN_SEND_PATH , OPEN_CHANNEL_PATH , SIGN_MESSAGE_PATH , SPLICE_IN_PATH , SPLICE_OUT_PATH ,
47- SPONTANEOUS_SEND_PATH , UNIFIED_SEND_PATH , UPDATE_CHANNEL_CONFIG_PATH , VERIFY_SIGNATURE_PATH ,
43+ GET_BALANCES_PATH , GET_METRICS_PATH , GET_NODE_INFO_PATH , GET_PAYMENT_DETAILS_PATH ,
44+ GRAPH_GET_CHANNEL_PATH , GRAPH_GET_NODE_PATH , GRAPH_LIST_CHANNELS_PATH , GRAPH_LIST_NODES_PATH ,
45+ LIST_CHANNELS_PATH , LIST_FORWARDED_PAYMENTS_PATH , LIST_PAYMENTS_PATH , LIST_PEERS_PATH ,
46+ ONCHAIN_RECEIVE_PATH , ONCHAIN_SEND_PATH , OPEN_CHANNEL_PATH , SIGN_MESSAGE_PATH , SPLICE_IN_PATH ,
47+ SPLICE_OUT_PATH , SPONTANEOUS_SEND_PATH , UNIFIED_SEND_PATH , UPDATE_CHANNEL_CONFIG_PATH ,
48+ VERIFY_SIGNATURE_PATH ,
4849} ;
4950use ldk_server_protos:: error:: { ErrorCode , ErrorResponse } ;
51+ use prost:: bytes:: Bytes ;
5052use prost:: Message ;
5153use reqwest:: header:: CONTENT_TYPE ;
5254use reqwest:: { Certificate , Client } ;
@@ -70,6 +72,11 @@ pub struct LdkServerClient {
7072 api_key : String ,
7173}
7274
75+ enum RequestType {
76+ Get ,
77+ Post ,
78+ }
79+
7380impl LdkServerClient {
7481 /// Constructs a [`LdkServerClient`] using `base_url` as the ldk-server endpoint.
7582 ///
@@ -115,6 +122,27 @@ impl LdkServerClient {
115122 self . post_request ( & request, & url) . await
116123 }
117124
125+ /// Retrieve the node metrics in Prometheus format.
126+ pub async fn get_metrics ( & self ) -> Result < String , LdkServerError > {
127+ self . get_metrics_with_auth ( None , None ) . await
128+ }
129+
130+ /// Retrieve the node metrics in Prometheus format using Basic Auth.
131+ pub async fn get_metrics_with_auth (
132+ & self , username : Option < & str > , password : Option < & str > ,
133+ ) -> Result < String , LdkServerError > {
134+ let url = format ! ( "https://{}/{GET_METRICS_PATH}" , self . base_url) ;
135+ let payload =
136+ self . make_request ( & url, RequestType :: Get , None , false , username, password) . await ?;
137+
138+ String :: from_utf8 ( payload. to_vec ( ) ) . map_err ( |e| {
139+ LdkServerError :: new (
140+ InternalError ,
141+ format ! ( "Failed to decode metrics response as string: {}" , e) ,
142+ )
143+ } )
144+ }
145+
118146 /// Retrieves an overview of all known balances.
119147 /// For API contract/usage, refer to docs for [`GetBalancesRequest`] and [`GetBalancesResponse`].
120148 pub async fn get_balances (
@@ -450,31 +478,60 @@ impl LdkServerClient {
450478 & self , request : & Rq , url : & str ,
451479 ) -> Result < Rs , LdkServerError > {
452480 let request_body = request. encode_to_vec ( ) ;
453- let auth_header = self . compute_auth_header ( & request_body) ;
454- let response_raw = self
455- . client
456- . post ( url)
457- . header ( CONTENT_TYPE , APPLICATION_OCTET_STREAM )
458- . header ( "X-Auth" , auth_header)
459- . body ( request_body)
460- . send ( )
461- . await
462- . map_err ( |e| {
463- LdkServerError :: new ( InternalError , format ! ( "HTTP request failed: {}" , e) )
464- } ) ?;
481+ let payload =
482+ self . make_request ( url, RequestType :: Post , Some ( request_body) , true , None , None ) . await ?;
483+ Rs :: decode ( & payload[ ..] ) . map_err ( |e| {
484+ LdkServerError :: new ( InternalError , format ! ( "Failed to decode success response: {}" , e) )
485+ } )
486+ }
487+
488+ async fn make_request (
489+ & self , url : & str , request_type : RequestType , body : Option < Vec < u8 > > ,
490+ hmac_authenticated : bool , metrics_username : Option < & str > , metrics_password : Option < & str > ,
491+ ) -> Result < Bytes , LdkServerError > {
492+ let builder = match request_type {
493+ RequestType :: Get => self . client . get ( url) ,
494+ RequestType :: Post => self . client . post ( url) ,
495+ } ;
496+
497+ let builder = if hmac_authenticated {
498+ let body_for_auth = body. as_deref ( ) . unwrap_or ( & [ ] ) ;
499+ let auth_header = self . compute_auth_header ( body_for_auth) ;
500+ builder. header ( "X-Auth" , auth_header)
501+ } else {
502+ builder
503+ } ;
504+
505+ let builder = if let Some ( body_content) = body {
506+ builder. header ( CONTENT_TYPE , APPLICATION_OCTET_STREAM ) . body ( body_content)
507+ } else {
508+ builder
509+ } ;
510+
511+ let builder = if let ( Some ( username) , Some ( password) ) = ( metrics_username, metrics_password)
512+ {
513+ builder. basic_auth ( username, Some ( password) )
514+ } else {
515+ builder
516+ } ;
517+
518+ let response_raw = builder. send ( ) . await . map_err ( |e| {
519+ LdkServerError :: new ( InternalError , format ! ( "HTTP request failed: {}" , e) )
520+ } ) ?;
465521
522+ self . handle_response ( response_raw) . await
523+ }
524+
525+ async fn handle_response (
526+ & self , response_raw : reqwest:: Response ,
527+ ) -> Result < Bytes , LdkServerError > {
466528 let status = response_raw. status ( ) ;
467529 let payload = response_raw. bytes ( ) . await . map_err ( |e| {
468530 LdkServerError :: new ( InternalError , format ! ( "Failed to read response body: {}" , e) )
469531 } ) ?;
470532
471533 if status. is_success ( ) {
472- Ok ( Rs :: decode ( & payload[ ..] ) . map_err ( |e| {
473- LdkServerError :: new (
474- InternalError ,
475- format ! ( "Failed to decode success response: {}" , e) ,
476- )
477- } ) ?)
534+ Ok ( payload)
478535 } else {
479536 let error_response = ErrorResponse :: decode ( & payload[ ..] ) . map_err ( |e| {
480537 LdkServerError :: new (
0 commit comments