22// Licensed under the MIT License.
33
44use super :: policies:: ClientRequestIdPolicy ;
5- use crate :: http:: {
6- headers:: { RETRY_AFTER_MS , X_MS_RETRY_AFTER_MS } ,
7- policies:: {
8- Policy , PublicApiInstrumentationPolicy , RequestInstrumentationPolicy , UserAgentPolicy ,
5+ use crate :: {
6+ error:: CheckSuccessOptions ,
7+ http:: {
8+ check_success,
9+ headers:: { RETRY_AFTER_MS , X_MS_RETRY_AFTER_MS } ,
10+ policies:: {
11+ Policy , PublicApiInstrumentationPolicy , RequestInstrumentationPolicy , UserAgentPolicy ,
12+ } ,
13+ ClientOptions ,
914 } ,
10- ClientOptions ,
1115} ;
1216use std:: {
1317 any:: { Any , TypeId } ,
14- ops:: Deref ,
1518 sync:: Arc ,
1619} ;
1720use typespec_client_core:: http:: {
@@ -40,6 +43,37 @@ use typespec_client_core::http::{
4043#[ derive( Debug , Clone ) ]
4144pub struct Pipeline ( http:: Pipeline ) ;
4245
46+ /// Options for sending a request through the pipeline.
47+ #[ derive( Debug , Default ) ]
48+ pub struct PipelineSendOptions {
49+ /// If true, skip all checks including `[check_success]`.
50+ pub skip_checks : bool ,
51+
52+ /// Options for `[check_success]`. If `skip_checks` is true, this field is ignored.
53+ pub check_success : CheckSuccessOptions ,
54+ }
55+
56+ /// Internal structure used to pass options to the core pipeline.
57+ #[ derive( Debug , Default ) ]
58+ struct CorePipelineSendOptions {
59+ check_success : CheckSuccessOptions ,
60+ skip_checks : bool ,
61+ }
62+
63+ impl PipelineSendOptions {
64+ /// Deconstructs the `PipelineSendOptions` into its core components.
65+ #[ expect( private_interfaces) ]
66+ pub fn deconstruct ( self ) -> ( CorePipelineSendOptions , Option < http:: PipelineSendOptions > ) {
67+ (
68+ CorePipelineSendOptions {
69+ skip_checks : self . skip_checks ,
70+ check_success : self . check_success ,
71+ } ,
72+ None ,
73+ )
74+ }
75+ }
76+
4377impl Pipeline {
4478 /// Creates a new pipeline given the client library crate name and version,
4579 /// alone with user-specified and client library-specified policies.
@@ -116,6 +150,32 @@ impl Pipeline {
116150 Some ( pipeline_options) ,
117151 ) )
118152 }
153+
154+ /// Sends the request through the pipeline, returning the response or an error.
155+ ///
156+ /// # Arguments
157+ /// * `ctx` - The context for the request.
158+ /// * `request` - The request to send.
159+ /// * `options` - Options for sending the request, including check success options. If none, `[check_success]` will not be called.
160+ ///
161+ /// # Returns
162+ /// A [`http::BufResponse`] if the request was successful, or an `Error` if it failed.
163+ /// If the response status code indicates an HTTP error, the function will attempt to parse the error response
164+ /// body into an `ErrorResponse` and include it in the `Error`.
165+ pub async fn send (
166+ & self ,
167+ ctx : & http:: Context < ' _ > ,
168+ request : & mut http:: Request ,
169+ options : Option < PipelineSendOptions > ,
170+ ) -> crate :: Result < http:: BufResponse > {
171+ let ( core_send_options, send_options) = options. unwrap_or_default ( ) . deconstruct ( ) ;
172+ let result = self . 0 . send ( ctx, request, send_options) . await ?;
173+ if !core_send_options. skip_checks {
174+ check_success ( result, Some ( core_send_options. check_success ) ) . await
175+ } else {
176+ Ok ( result)
177+ }
178+ }
119179}
120180
121181#[ inline]
@@ -125,13 +185,13 @@ fn push_unique<T: Policy + 'static>(policies: &mut Vec<Arc<dyn Policy>>, policy:
125185 }
126186}
127187
128- // TODO: Should we instead use the newtype pattern?
129- impl Deref for Pipeline {
130- type Target = http:: Pipeline ;
131- fn deref ( & self ) -> & Self :: Target {
132- & self . 0
133- }
134- }
188+ // // TODO: Should we instead use the newtype pattern?
189+ // impl Deref for Pipeline {
190+ // type Target = http::Pipeline;
191+ // fn deref(&self) -> &Self::Target {
192+ // &self.0
193+ // }
194+ // }
135195
136196#[ cfg( test) ]
137197mod tests {
@@ -205,7 +265,7 @@ mod tests {
205265
206266 // Act
207267 pipeline
208- . send ( & ctx, & mut request)
268+ . send ( & ctx, & mut request, None )
209269 . await
210270 . expect ( "Pipeline execution failed" ) ;
211271 }
@@ -259,7 +319,7 @@ mod tests {
259319
260320 // Act
261321 pipeline
262- . send ( & ctx, & mut request)
322+ . send ( & ctx, & mut request, None )
263323 . await
264324 . expect ( "Pipeline execution failed" ) ;
265325 }
@@ -313,7 +373,7 @@ mod tests {
313373
314374 // Act
315375 pipeline
316- . send ( & ctx, & mut request)
376+ . send ( & ctx, & mut request, None )
317377 . await
318378 . expect ( "Pipeline execution failed" ) ;
319379 }
@@ -374,7 +434,7 @@ mod tests {
374434
375435 // Act
376436 pipeline
377- . send ( & ctx, & mut request)
437+ . send ( & ctx, & mut request, None )
378438 . await
379439 . expect ( "Pipeline execution failed" ) ;
380440 }
0 commit comments