11
22use axum:: {
3- body:: Body ,
4- extract:: { DefaultBodyLimit , Query } ,
5- response:: { IntoResponse , Redirect , Response } ,
6- routing:: get,
7- Json , Router ,
3+ body:: Body , extract:: { DefaultBodyLimit , Query } , response:: { IntoResponse , Response } , routing:: { get, post} , Json , Router
84} ;
5+ use axum_extra:: extract:: Form ;
96
107use rustc_version_runtime:: version;
118use serde:: { Deserialize , Serialize } ;
129use tower_http:: { limit:: RequestBodyLimitLayer , services:: ServeFile } ;
10+ use html_escape:: encode_text;
1311
1412#[ tokio:: main]
1513async fn main ( ) {
1614 // build our application with a single route
1715 let app = Router :: new ( )
18- //.route_service("/", get(|| async { Redirect::temporary("https://www.regexplanet.com/advanced/rust/index.html") }))
16+ //.route_service("/", get(|| async { axum:: Redirect::temporary("https://www.regexplanet.com/advanced/rust/index.html") }))
1917 . route_service ( "/" , get ( root_handler) )
18+ . route_service ( "/test.json" , post ( test_handler) )
2019 . route_service ( "/favicon.ico" , ServeFile :: new ( "static/favicon.ico" ) )
2120 . route_service ( "/favicon.svg" , ServeFile :: new ( "static/favicon.svg" ) )
2221 . route_service ( "/robots.txt" , ServeFile :: new ( "static/robots.txt" ) )
2322 . route_service ( "/status.json" , get ( get_status) )
2423 . layer ( DefaultBodyLimit :: disable ( ) )
2524 . layer ( RequestBodyLimitLayer :: new ( 10 * 1024 * 1024 /* 10mb */ ) ) ;
2625
27- // run our app with hyper, listening globally on port 3000
28-
2926 // get address from environment variable
3027 let address = std:: env:: var ( "ADDRESS" ) . unwrap_or_else ( |_| "0.0.0.0" . to_string ( ) ) ;
3128
@@ -89,4 +86,121 @@ async fn root_handler() -> Response<Body> {
8986 . header ( "Content-Type" , "text/plain; charset=utf-8" )
9087 . body ( Body :: from ( "Dev server running!" ) )
9188 . unwrap ( ) ;
89+ }
90+
91+ #[ derive( Deserialize , Serialize , Debug ) ]
92+ struct TestInput {
93+ regex : String ,
94+ #[ serde( default ) ]
95+ replacement : String ,
96+ #[ serde( default ) ]
97+ callback : String ,
98+ #[ serde( default ) ]
99+ options : Vec < String > ,
100+ #[ serde( default ) ]
101+ #[ serde( rename( deserialize = "input" ) ) ]
102+ inputs : Vec < String > ,
103+ }
104+
105+ #[ derive( Serialize ) ]
106+ struct TestOutput {
107+ success : bool ,
108+ message : String ,
109+ html : String ,
110+ }
111+
112+ async fn test_handler ( Form ( test_input) : Form < TestInput > ) -> Response < Body > {
113+
114+ let mut html = String :: new ( ) ;
115+
116+ html. push_str ( "<table class=\" table table-bordered table-striped\" style=\" width: auto;\" >\n " ) ;
117+ html. push_str ( "\t <tbody>\n " ) ;
118+ html. push_str ( "\t \t <tr>\n " ) ;
119+ html. push_str ( "\t \t \t <td>Regular Expression</td>\n " ) ;
120+ html. push_str ( & format ! ( "\t \t \t <td><code>{}</code></td>\n " , encode_text( & test_input. regex) ) ) ;
121+ html. push_str ( "\t \t </tr>\n " ) ;
122+
123+ if test_input. replacement != "" {
124+ html. push_str ( "\t \t <tr>\n " ) ;
125+ html. push_str ( "\t \t \t <td>Replacement</td>\n " ) ;
126+ html. push_str ( & format ! ( "\t \t \t <td><code>{}</code></td>\n " , encode_text( & test_input. replacement) ) ) ;
127+ html. push_str ( "\t \t </tr>\n " ) ;
128+ }
129+
130+ html. push_str ( "\t </tbody>\n " ) ;
131+ html. push_str ( "</table>" ) ;
132+
133+ let the_regex = regex:: RegexBuilder :: new ( & test_input. regex )
134+ . case_insensitive ( test_input. options . contains ( & "i" . to_string ( ) ) )
135+ . multi_line ( test_input. options . contains ( & "m" . to_string ( ) ) )
136+ . dot_matches_new_line ( test_input. options . contains ( & "s" . to_string ( ) ) )
137+ . build ( ) ;
138+
139+ if the_regex. is_err ( ) {
140+ let err_msg = the_regex. unwrap_err ( ) . to_string ( ) ;
141+
142+ html. push_str ( "<div class=\" alert alert-danger\" role=\" alert\" >\n " ) ;
143+ html. push_str ( & format ! ( "<strong>Error:</strong> {}<br>\n " , encode_text( & err_msg) ) ) ;
144+ html. push_str ( "</div>\n " ) ;
145+
146+ return handle_jsonp ( & test_input. callback , html) ;
147+ }
148+
149+ if test_input. inputs . len ( ) == 0 {
150+ html. push_str ( "<div class=\" alert alert-danger\" role=\" alert\" >\n " ) ;
151+ html. push_str ( "No inputs to test!\n " ) ;
152+ html. push_str ( "</div>\n " ) ;
153+
154+ return handle_jsonp ( & test_input. callback , html) ;
155+ }
156+
157+ let the_regex = the_regex. unwrap ( ) ;
158+
159+ html. push_str ( "<table class=\" table table-bordered table-striped\" style=\" width: auto;\" >\n " ) ;
160+ html. push_str ( "\t <thead>\n " ) ;
161+ html. push_str ( "\t \t <tr>\n " ) ;
162+ html. push_str ( "\t \t \t <th>Input</th>\n " ) ;
163+ html. push_str ( "\t \t \t <th>is_match</th>\n " ) ;
164+ html. push_str ( "\t \t </tr>\n " ) ;
165+ html. push_str ( "\t </thead>\n " ) ;
166+ html. push_str ( "\t <tbody>\n " ) ;
167+
168+ for input in test_input. inputs {
169+ //let output = the_regex.as_ref().unwrap().replace_all(&input, &test_input.replacement);
170+ html. push_str ( "\t \t <tr>\n " ) ;
171+ html. push_str ( & format ! ( "\t \t \t <td>{}</td>\n " , encode_text( & input) ) ) ;
172+ let is_match = if the_regex. is_match ( & input) { "true" } else { "false" } ;
173+ html. push_str ( & format ! ( "\t \t \t <td>{}</td>\n " , is_match) ) ;
174+ html. push_str ( "\t \t </tr>\n " ) ;
175+ }
176+
177+ html. push_str ( "\t </tbody>\n " ) ;
178+ html. push_str ( "</table>" ) ;
179+
180+ return handle_jsonp ( & test_input. callback , html) ;
181+ }
182+
183+ fn handle_jsonp ( callback : & str , html : String ) -> Response < Body > {
184+
185+
186+ let test_output = TestOutput {
187+ success : true ,
188+ message : "OK" . to_string ( ) ,
189+ html : html,
190+ } ;
191+
192+ let json_output = serde_json:: to_string ( & test_output) . unwrap ( ) ;
193+
194+ if callback == "" {
195+ return Response :: builder ( )
196+ . header ( "Content-Type" , "application/json; charset=utf-8" )
197+ . body ( Body :: from ( json_output) )
198+ . unwrap ( ) ;
199+ } else {
200+ let jsonp = format ! ( "{}({})" , callback, json_output) ;
201+ return Response :: builder ( )
202+ . header ( "Content-Type" , "text/html; charset=utf-8" )
203+ . body ( Body :: from ( jsonp) )
204+ . unwrap ( ) ;
205+ }
92206}
0 commit comments