11use crate :: action:: { Action , UnitTrace } ;
2+ use crate :: api:: rules_message:: RuleChangeSet ;
23use crate :: api:: { Example , Rule } ;
34use crate :: http:: Header ;
45use crate :: http:: Request ;
56use crate :: router:: { Router , RouterConfig , Trace } ;
67use serde:: { Deserialize , Serialize } ;
8+ use std:: sync:: Arc ;
79use url:: Url ;
810
911const REDIRECTION_CODES : [ u16 ; 4 ] = [ 301 , 302 , 307 , 308 ] ;
@@ -20,6 +22,15 @@ pub struct ImpactInput {
2022 pub rules : TmpRules ,
2123}
2224
25+ #[ derive( Deserialize , Debug , Clone ) ]
26+ pub struct ImpactProjectInput {
27+ pub max_hops : u8 ,
28+ pub with_redirection_loop : bool ,
29+ pub rule : Rule ,
30+ pub action : String ,
31+ pub change_set : RuleChangeSet ,
32+ }
33+
2334// FIXME: find a way to avoid creating this structure.
2435// It would be more convenient to inline the structure
2536#[ derive( Deserialize , Debug , Clone ) ]
@@ -92,6 +103,28 @@ impl Impact {
92103}
93104
94105impl ImpactOutput {
106+ pub fn from_impact_project ( impact_input : ImpactProjectInput , existing_router : Arc < Router < Rule > > ) -> ImpactOutput {
107+ let mut impact_router = impact_input. change_set . update_existing_router ( existing_router. clone ( ) ) ;
108+ let mut trace_unique_router = Router :: < Rule > :: from_arc_config ( existing_router. config . clone ( ) ) ;
109+
110+ impact_router. remove ( impact_input. rule . id . as_str ( ) ) ;
111+
112+ if impact_input. action == "add" || impact_input. action == "update" {
113+ impact_router. insert ( impact_input. rule . clone ( ) ) ;
114+ trace_unique_router. insert ( impact_input. rule . clone ( ) ) ;
115+ }
116+
117+ let impacts = ImpactOutput :: compute_impacts (
118+ & impact_router,
119+ & trace_unique_router,
120+ impact_input. rule . examples ,
121+ impact_input. with_redirection_loop ,
122+ impact_input. max_hops ,
123+ ) ;
124+
125+ ImpactOutput { impacts }
126+ }
127+
95128 pub fn create_result ( impact_input : ImpactInput ) -> ImpactOutput {
96129 let mut router = Router :: < Rule > :: from_config ( impact_input. router_config . clone ( ) ) ;
97130 let mut trace_unique_router = Router :: < Rule > :: from_config ( impact_input. router_config . clone ( ) ) ;
@@ -104,23 +137,40 @@ impl ImpactOutput {
104137 if rule. id == impact_input. rule . id {
105138 continue ;
106139 }
107- router. insert ( rule. clone ( ) . into_route ( & impact_input . router_config ) ) ;
140+ router. insert ( rule. clone ( ) ) ;
108141 }
109142
110143 if impact_input. action == "add" || impact_input. action == "update" {
111- router. insert ( impact_input. rule . clone ( ) . into_route ( & impact_input . router_config ) ) ;
112- trace_unique_router. insert ( impact_input. rule . clone ( ) . into_route ( & impact_input . router_config ) ) ;
144+ router. insert ( impact_input. rule . clone ( ) ) ;
145+ trace_unique_router. insert ( impact_input. rule . clone ( ) ) ;
113146 }
114147
115- let impacts = ImpactOutput :: compute_impacts ( & router, & trace_unique_router, & impact_input) ;
148+ let impacts = ImpactOutput :: compute_impacts (
149+ & router,
150+ & trace_unique_router,
151+ impact_input. rule . examples ,
152+ impact_input. with_redirection_loop ,
153+ impact_input. max_hops ,
154+ ) ;
116155
117156 ImpactOutput { impacts }
118157 }
119158
120- fn compute_impacts ( router : & Router < Rule > , trace_unique_router : & Router < Rule > , impact_input : & ImpactInput ) -> Vec < Impact > {
159+ fn compute_impacts (
160+ router : & Router < Rule > ,
161+ trace_unique_router : & Router < Rule > ,
162+ examples : Option < Vec < Example > > ,
163+ with_redirection_loop : bool ,
164+ max_hops : u8 ,
165+ ) -> Vec < Impact > {
121166 let mut impacts = Vec :: new ( ) ;
122- for example in impact_input. rule . examples . as_ref ( ) . unwrap ( ) . iter ( ) {
123- let request = match Request :: from_example ( & router. config , example) {
167+
168+ if examples. is_none ( ) {
169+ return impacts;
170+ }
171+
172+ for example in examples. unwrap ( ) {
173+ let request = match Request :: from_example ( & router. config , & example) {
124174 Ok ( request) => request,
125175 Err ( e) => {
126176 impacts. push ( Impact :: new_with_error (
@@ -163,8 +213,8 @@ impl ImpactOutput {
163213
164214 unit_trace. squash_with_target_unit_traces ( ) ;
165215
166- let redirection_loop = if impact_input . with_redirection_loop {
167- Some ( ImpactOutput :: compute_redirection_loop ( router, impact_input , example) )
216+ let redirection_loop = if with_redirection_loop {
217+ Some ( ImpactOutput :: compute_redirection_loop ( router, max_hops , & example) )
168218 } else {
169219 None
170220 } ;
@@ -187,7 +237,7 @@ impl ImpactOutput {
187237 impacts
188238 }
189239
190- fn compute_redirection_loop ( router : & Router < Rule > , impact_input : & ImpactInput , example : & Example ) -> RedirectionLoop {
240+ fn compute_redirection_loop ( router : & Router < Rule > , max_hops : u8 , example : & Example ) -> RedirectionLoop {
191241 let mut current_url = example. url . clone ( ) ;
192242 let mut current_method = example. method . clone ( ) . unwrap_or ( String :: from ( "GET" ) ) ;
193243 let mut error = None ;
@@ -198,7 +248,7 @@ impl ImpactOutput {
198248 method: current_method. clone( ) ,
199249 } ] ;
200250
201- ' outer: for i in 1 ..=impact_input . max_hops {
251+ ' outer: for i in 1 ..=max_hops {
202252 let new_example = example. with_url ( current_url. clone ( ) ) . with_method ( Some ( current_method. clone ( ) ) ) ;
203253
204254 let request = Request :: from_example ( & router. config , & new_example) . unwrap ( ) ;
@@ -260,7 +310,7 @@ impl ImpactOutput {
260310 method : current_method. clone ( ) ,
261311 } ) ;
262312
263- if i >= impact_input . max_hops {
313+ if i >= max_hops {
264314 error = Some ( RedirectionError :: TooManyHops ) ;
265315 break ;
266316 }
0 commit comments