66//! Endpoint override detection for business metrics tracking
77
88use aws_smithy_runtime_api:: box_error:: BoxError ;
9- use aws_smithy_runtime_api:: client:: interceptors:: context:: BeforeTransmitInterceptorContextRef ;
9+ use aws_smithy_runtime_api:: client:: interceptors:: context:: BeforeSerializationInterceptorContextRef ;
1010use aws_smithy_runtime_api:: client:: interceptors:: Intercept ;
11- use aws_smithy_runtime_api:: client:: runtime_components:: RuntimeComponents ;
1211use aws_smithy_runtime_api:: client:: runtime_plugin:: RuntimePlugin ;
13- use aws_smithy_types:: config_bag:: { ConfigBag , FrozenLayer , Layer } ;
12+ use aws_smithy_types:: config_bag:: { ConfigBag , FrozenLayer } ;
1413
1514use crate :: sdk_feature:: AwsSdkFeature ;
1615
1716/// Interceptor that detects custom endpoint URLs for business metrics
18- ///
19- /// This interceptor checks at runtime if a `StaticUriEndpointResolver` is configured,
20- /// which indicates that `.endpoint_url()` was called. When detected, it stores the
21- /// `AwsSdkFeature::EndpointOverride` feature flag for business metrics tracking.
2217#[ derive( Debug , Default ) ]
2318#[ non_exhaustive]
2419pub struct EndpointOverrideInterceptor ;
@@ -35,25 +30,19 @@ impl Intercept for EndpointOverrideInterceptor {
3530 "EndpointOverrideInterceptor"
3631 }
3732
38- fn read_after_serialization (
33+ fn read_before_execution (
3934 & self ,
40- _context : & BeforeTransmitInterceptorContextRef < ' _ > ,
41- runtime_components : & RuntimeComponents ,
35+ _context : & BeforeSerializationInterceptorContextRef < ' _ > ,
4236 cfg : & mut ConfigBag ,
4337 ) -> Result < ( ) , BoxError > {
44- // Check if the endpoint resolver is a StaticUriEndpointResolver
45- // This indicates that .endpoint_url() was called
46- let resolver = runtime_components. endpoint_resolver ( ) ;
47-
48- // Check the resolver's debug string to see if it's StaticUriEndpointResolver
49- let debug_str = format ! ( "{resolver:?}" ) ;
50-
51- if debug_str. contains ( "StaticUriEndpointResolver" ) {
52- // Store in interceptor_state
38+ // Check if endpoint_url was set in config
39+ if cfg
40+ . load :: < aws_types:: endpoint_config:: EndpointUrl > ( )
41+ . is_some ( )
42+ {
5343 cfg. interceptor_state ( )
5444 . store_append ( AwsSdkFeature :: EndpointOverride ) ;
5545 }
56-
5746 Ok ( ( ) )
5847 }
5948}
@@ -76,15 +65,6 @@ impl EndpointOverrideRuntimePlugin {
7665 pub fn new ( config : Option < FrozenLayer > ) -> Self {
7766 Self { config }
7867 }
79-
80- /// Creates a new `EndpointOverrideRuntimePlugin` and marks that endpoint override is enabled
81- pub fn new_with_feature_flag ( ) -> Self {
82- let mut layer = Layer :: new ( "endpoint_override" ) ;
83- layer. store_append ( AwsSdkFeature :: EndpointOverride ) ;
84- Self {
85- config : Some ( layer. freeze ( ) ) ,
86- }
87- }
8868}
8969
9070impl RuntimePlugin for EndpointOverrideRuntimePlugin {
@@ -97,6 +77,10 @@ impl RuntimePlugin for EndpointOverrideRuntimePlugin {
9777mod tests {
9878 use super :: * ;
9979 use crate :: sdk_feature:: AwsSdkFeature ;
80+ use aws_smithy_runtime_api:: client:: interceptors:: context:: {
81+ BeforeSerializationInterceptorContextRef , Input , InterceptorContext ,
82+ } ;
83+ use aws_smithy_types:: config_bag:: ConfigBag ;
10084
10185 #[ test]
10286 fn test_plugin_with_no_config ( ) {
@@ -105,55 +89,56 @@ mod tests {
10589 }
10690
10791 #[ test]
108- fn test_plugin_with_feature_flag ( ) {
109- let plugin = EndpointOverrideRuntimePlugin :: new_with_feature_flag ( ) ;
110- let config = plugin. config ( ) . expect ( "config should be set" ) ;
92+ fn test_interceptor_detects_endpoint_url_when_present ( ) {
93+ let interceptor = EndpointOverrideInterceptor :: new ( ) ;
94+ let mut cfg = ConfigBag :: base ( ) ;
95+
96+ // Set endpoint URL in config
97+ let endpoint_url =
98+ aws_types:: endpoint_config:: EndpointUrl ( "https://custom.example.com" . to_string ( ) ) ;
99+ cfg. interceptor_state ( ) . store_put ( endpoint_url) ;
100+
101+ // Create a dummy context
102+ let input = Input :: doesnt_matter ( ) ;
103+ let ctx = InterceptorContext :: new ( input) ;
104+ let context = BeforeSerializationInterceptorContextRef :: from ( & ctx) ;
105+
106+ // Run the interceptor
107+ interceptor
108+ . read_before_execution ( & context, & mut cfg)
109+ . unwrap ( ) ;
111110
112- // Verify the feature flag is present in the config
113- let features: Vec < _ > = config. load :: < AwsSdkFeature > ( ) . cloned ( ) . collect ( ) ;
111+ // Verify feature flag was set in interceptor_state
112+ let features: Vec < _ > = cfg
113+ . interceptor_state ( )
114+ . load :: < AwsSdkFeature > ( )
115+ . cloned ( )
116+ . collect ( ) ;
114117 assert_eq ! ( features. len( ) , 1 ) ;
115118 assert_eq ! ( features[ 0 ] , AwsSdkFeature :: EndpointOverride ) ;
116119 }
117120
118121 #[ test]
119- fn test_interceptor_detects_static_uri_resolver ( ) {
120- use aws_smithy_runtime:: client:: orchestrator:: endpoints:: StaticUriEndpointResolver ;
121- use aws_smithy_runtime_api:: client:: endpoint:: SharedEndpointResolver ;
122- use aws_smithy_runtime_api:: client:: interceptors:: context:: { Input , InterceptorContext } ;
123- use aws_smithy_runtime_api:: client:: orchestrator:: HttpRequest ;
124- use aws_smithy_runtime_api:: client:: runtime_components:: RuntimeComponentsBuilder ;
125- use aws_smithy_types:: config_bag:: ConfigBag ;
126-
127- // Create a StaticUriEndpointResolver
128- let endpoint_resolver = SharedEndpointResolver :: new ( StaticUriEndpointResolver :: uri (
129- "https://custom.example.com" ,
130- ) ) ;
131-
132- let mut context = InterceptorContext :: new ( Input :: doesnt_matter ( ) ) ;
133- context. enter_serialization_phase ( ) ;
134- context. set_request ( HttpRequest :: empty ( ) ) ;
135- let _ = context. take_input ( ) ;
136- context. enter_before_transmit_phase ( ) ;
137-
138- let rc = RuntimeComponentsBuilder :: for_tests ( )
139- . with_endpoint_resolver ( Some ( endpoint_resolver) )
140- . build ( )
141- . unwrap ( ) ;
122+ fn test_interceptor_does_not_set_flag_when_endpoint_url_absent ( ) {
123+ let interceptor = EndpointOverrideInterceptor :: new ( ) ;
142124 let mut cfg = ConfigBag :: base ( ) ;
143125
144- let interceptor = EndpointOverrideInterceptor :: new ( ) ;
145- let ctx = Into :: into ( & context) ;
126+ // Create a dummy context
127+ let input = Input :: doesnt_matter ( ) ;
128+ let ctx = InterceptorContext :: new ( input) ;
129+ let context = BeforeSerializationInterceptorContextRef :: from ( & ctx) ;
130+
131+ // Run the interceptor without setting endpoint URL
146132 interceptor
147- . read_after_serialization ( & ctx , & rc , & mut cfg)
133+ . read_before_execution ( & context , & mut cfg)
148134 . unwrap ( ) ;
149135
150- // Verify the feature flag was set
136+ // Verify no feature flag was set
151137 let features: Vec < _ > = cfg
152138 . interceptor_state ( )
153139 . load :: < AwsSdkFeature > ( )
154140 . cloned ( )
155141 . collect ( ) ;
156- assert_eq ! ( features. len( ) , 1 , "Expected 1 feature, got: {features:?}" ) ;
157- assert_eq ! ( features[ 0 ] , AwsSdkFeature :: EndpointOverride ) ;
142+ assert_eq ! ( features. len( ) , 0 ) ;
158143 }
159144}
0 commit comments