@@ -35,7 +35,6 @@ use std::time::Duration;
3535use thiserror:: Error ;
3636use tokio:: sync:: { mpsc, oneshot} ;
3737use tokio_util:: sync:: PollSender ;
38- use tracing:: trace;
3938
4039static VERSION_RE : Lazy < Regex > =
4140 Lazy :: new ( || Regex :: new ( r"\Av?([0-9]+)\.?([0-9]+)?\.?([0-9]+)?" ) . unwrap ( ) ) ;
@@ -88,6 +87,7 @@ pub struct Client {
8887 request_timeout : Option < Duration > ,
8988 max_payload : Arc < AtomicUsize > ,
9089 connection_stats : Arc < Statistics > ,
90+ skip_subject_validation : bool ,
9191}
9292
9393pub mod traits {
@@ -100,30 +100,37 @@ pub mod traits {
100100 use super :: { PublishError , Request , RequestError , SubscribeError } ;
101101
102102 pub trait Publisher {
103- fn publish_with_reply < S : ToSubject , R : ToSubject > (
103+ fn publish_with_reply < S , R > (
104104 & self ,
105105 subject : S ,
106106 reply : R ,
107107 payload : Bytes ,
108- ) -> impl Future < Output = Result < ( ) , PublishError > > ;
108+ ) -> impl Future < Output = Result < ( ) , PublishError > >
109+ where
110+ S : ToSubject ,
111+ R : ToSubject ;
109112
110113 fn publish_message (
111114 & self ,
112115 msg : message:: OutboundMessage ,
113116 ) -> impl Future < Output = Result < ( ) , PublishError > > ;
114117 }
115118 pub trait Subscriber {
116- fn subscribe < S : ToSubject > (
119+ fn subscribe < S > (
117120 & self ,
118121 subject : S ,
119- ) -> impl Future < Output = Result < crate :: Subscriber , SubscribeError > > ;
122+ ) -> impl Future < Output = Result < crate :: Subscriber , SubscribeError > >
123+ where
124+ S : ToSubject ;
120125 }
121126 pub trait Requester {
122- fn send_request < S : ToSubject > (
127+ fn send_request < S > (
123128 & self ,
124129 subject : S ,
125130 request : Request ,
126- ) -> impl Future < Output = Result < Message , RequestError > > ;
131+ ) -> impl Future < Output = Result < Message , RequestError > >
132+ where
133+ S : ToSubject ;
127134 }
128135 pub trait TimeoutProvider {
129136 fn timeout ( & self ) -> Option < Duration > ;
@@ -147,12 +154,16 @@ impl traits::TimeoutProvider for Client {
147154}
148155
149156impl traits:: Publisher for Client {
150- fn publish_with_reply < S : ToSubject , R : ToSubject > (
157+ fn publish_with_reply < S , R > (
151158 & self ,
152159 subject : S ,
153160 reply : R ,
154161 payload : Bytes ,
155- ) -> impl Future < Output = Result < ( ) , PublishError > > {
162+ ) -> impl Future < Output = Result < ( ) , PublishError > >
163+ where
164+ S : ToSubject ,
165+ R : ToSubject ,
166+ {
156167 self . publish_with_reply ( subject, reply, payload)
157168 }
158169
@@ -165,10 +176,10 @@ impl traits::Publisher for Client {
165176}
166177
167178impl traits:: Subscriber for Client {
168- fn subscribe < S : ToSubject > (
169- & self ,
170- subject : S ,
171- ) -> impl Future < Output = Result < Subscriber , SubscribeError > > {
179+ fn subscribe < S > ( & self , subject : S ) -> impl Future < Output = Result < Subscriber , SubscribeError > >
180+ where
181+ S : ToSubject ,
182+ {
172183 self . subscribe ( subject)
173184 }
174185}
@@ -206,6 +217,7 @@ impl Client {
206217 request_timeout : Option < Duration > ,
207218 max_payload : Arc < AtomicUsize > ,
208219 statistics : Arc < Statistics > ,
220+ skip_subject_validation : bool ,
209221 ) -> Client {
210222 let poll_sender = PollSender :: new ( sender. clone ( ) ) ;
211223 Client {
@@ -219,7 +231,25 @@ impl Client {
219231 request_timeout,
220232 max_payload,
221233 connection_stats : statistics,
234+ skip_subject_validation,
235+ }
236+ }
237+
238+ /// Converts a subject to a [`Subject`], optionally validating it.
239+ ///
240+ /// If subject validation is enabled (the default), the subject is validated
241+ /// before conversion. If validation is disabled via
242+ /// [`ConnectOptions::skip_subject_validation`], the subject is converted
243+ /// without validation.
244+ fn maybe_validate_subject < S : ToSubject > (
245+ & self ,
246+ subject : S ,
247+ ) -> Result < crate :: Subject , crate :: subject:: SubjectError > {
248+ let subject = subject. to_subject ( ) ;
249+ if !self . skip_subject_validation && !subject. is_valid ( ) {
250+ return Err ( crate :: subject:: SubjectError :: InvalidFormat ) ;
222251 }
252+ Ok ( subject)
223253 }
224254
225255 /// Returns the default timeout for requests set when creating the client.
@@ -318,7 +348,10 @@ impl Client {
318348 subject : S ,
319349 payload : Bytes ,
320350 ) -> Result < ( ) , PublishError > {
321- let subject = subject. to_subject ( ) ;
351+ let subject = self
352+ . maybe_validate_subject ( subject)
353+ . map_err ( |e| PublishError :: with_source ( PublishErrorKind :: BadSubject , e) ) ?;
354+
322355 let max_payload = self . max_payload . load ( Ordering :: Relaxed ) ;
323356 if payload. len ( ) > max_payload {
324357 return Err ( PublishError :: with_source (
@@ -367,7 +400,9 @@ impl Client {
367400 headers : HeaderMap ,
368401 payload : Bytes ,
369402 ) -> Result < ( ) , PublishError > {
370- let subject = subject. to_subject ( ) ;
403+ let subject = self
404+ . maybe_validate_subject ( subject)
405+ . map_err ( |e| PublishError :: with_source ( PublishErrorKind :: BadSubject , e) ) ?;
371406
372407 self . sender
373408 . send ( Command :: Publish ( OutboundMessage {
@@ -402,8 +437,12 @@ impl Client {
402437 reply : R ,
403438 payload : Bytes ,
404439 ) -> Result < ( ) , PublishError > {
405- let subject = subject. to_subject ( ) ;
406- let reply = reply. to_subject ( ) ;
440+ let subject = self
441+ . maybe_validate_subject ( subject)
442+ . map_err ( |e| PublishError :: with_source ( PublishErrorKind :: BadSubject , e) ) ?;
443+ let reply = self
444+ . maybe_validate_subject ( reply)
445+ . map_err ( |e| PublishError :: with_source ( PublishErrorKind :: BadSubject , e) ) ?;
407446
408447 self . sender
409448 . send ( Command :: Publish ( OutboundMessage {
@@ -441,8 +480,12 @@ impl Client {
441480 headers : HeaderMap ,
442481 payload : Bytes ,
443482 ) -> Result < ( ) , PublishError > {
444- let subject = subject. to_subject ( ) ;
445- let reply = reply. to_subject ( ) ;
483+ let subject = self
484+ . maybe_validate_subject ( subject)
485+ . map_err ( |e| PublishError :: with_source ( PublishErrorKind :: BadSubject , e) ) ?;
486+ let reply = self
487+ . maybe_validate_subject ( reply)
488+ . map_err ( |e| PublishError :: with_source ( PublishErrorKind :: BadSubject , e) ) ?;
446489
447490 self . sender
448491 . send ( Command :: Publish ( OutboundMessage {
@@ -471,13 +514,6 @@ impl Client {
471514 subject : S ,
472515 payload : Bytes ,
473516 ) -> Result < Message , RequestError > {
474- let subject = subject. to_subject ( ) ;
475-
476- trace ! (
477- "request sent to subject: {} ({})" ,
478- subject. as_ref( ) ,
479- payload. len( )
480- ) ;
481517 let request = Request :: new ( ) . payload ( payload) ;
482518 self . send_request ( subject, request) . await
483519 }
@@ -503,8 +539,6 @@ impl Client {
503539 headers : HeaderMap ,
504540 payload : Bytes ,
505541 ) -> Result < Message , RequestError > {
506- let subject = subject. to_subject ( ) ;
507-
508542 let request = Request :: new ( ) . headers ( headers) . payload ( payload) ;
509543 self . send_request ( subject, request) . await
510544 }
@@ -527,7 +561,9 @@ impl Client {
527561 subject : S ,
528562 request : Request ,
529563 ) -> Result < Message , RequestError > {
530- let subject = subject. to_subject ( ) ;
564+ let subject = self
565+ . maybe_validate_subject ( subject)
566+ . map_err ( |e| RequestError :: with_source ( RequestErrorKind :: Other , e) ) ?;
531567
532568 if let Some ( inbox) = request. inbox {
533569 let timeout = request. timeout . unwrap_or ( self . request_timeout ) ;
@@ -640,7 +676,13 @@ impl Client {
640676 /// # }
641677 /// ```
642678 pub async fn subscribe < S : ToSubject > ( & self , subject : S ) -> Result < Subscriber , SubscribeError > {
643- let subject = subject. to_subject ( ) ;
679+ let subject = self . maybe_validate_subject ( subject) . map_err ( |e| {
680+ SubscribeError ( Box :: new ( std:: io:: Error :: new (
681+ std:: io:: ErrorKind :: InvalidInput ,
682+ e,
683+ ) ) )
684+ } ) ?;
685+
644686 let sid = self . next_subscription_id . fetch_add ( 1 , Ordering :: Relaxed ) ;
645687 let ( sender, receiver) = mpsc:: channel ( self . subscription_capacity ) ;
646688
@@ -677,7 +719,12 @@ impl Client {
677719 subject : S ,
678720 queue_group : String ,
679721 ) -> Result < Subscriber , SubscribeError > {
680- let subject = subject. to_subject ( ) ;
722+ let subject = self . maybe_validate_subject ( subject) . map_err ( |e| {
723+ SubscribeError ( Box :: new ( std:: io:: Error :: new (
724+ std:: io:: ErrorKind :: InvalidInput ,
725+ e,
726+ ) ) )
727+ } ) ?;
681728
682729 let sid = self . next_subscription_id . fetch_add ( 1 , Ordering :: Relaxed ) ;
683730 let ( sender, receiver) = mpsc:: channel ( self . subscription_capacity ) ;
0 commit comments