use futures - first try
This commit is contained in:
		| @ -17,6 +17,8 @@ serde = "1.0.80" | ||||
| serde_json = "1.0.32" | ||||
| serde_derive = "1.0.80" | ||||
| url = "1.7.1" | ||||
| hyper = "0.12.13" | ||||
| futures = "0.1.25" | ||||
| http = "0.1.13" | ||||
| hyper = "0.12.14" | ||||
| lazy_static = "1.1.0" | ||||
| regex = "1.0.6" | ||||
|  | ||||
							
								
								
									
										96
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -13,24 +13,73 @@ use apitest::json_schema::*; | ||||
| use serde_json::{json, Value}; | ||||
|  | ||||
|  | ||||
| use hyper::body::Payload; | ||||
| use hyper::http::request::Parts; | ||||
| use hyper::{Method, Body, Request, Response, Server, StatusCode}; | ||||
| use hyper::rt::Future; | ||||
| use hyper::service::service_fn_ok; | ||||
| use hyper::rt::{Future, Stream}; | ||||
| use hyper::service::service_fn; | ||||
|  | ||||
| use futures::prelude::*; | ||||
| use futures::future; | ||||
|  | ||||
| use http; | ||||
| use std::io; | ||||
|  | ||||
| type BoxFut = Box<Future<Item = Response<Body>, Error = hyper::Error> + Send>; | ||||
|  | ||||
| macro_rules! http_error { | ||||
|     ($status:ident, $msg:expr) => {{ | ||||
|         let mut resp = Response::new(Body::from($msg)); | ||||
|         *resp.status_mut() = StatusCode::$status; | ||||
|         return resp; | ||||
|         return resp | ||||
|     }} | ||||
| } | ||||
| macro_rules! http_error_future { | ||||
|     ($status:ident, $msg:expr) => {{ | ||||
|         let mut resp = Response::new(Body::from($msg)); | ||||
|         *resp.status_mut() = StatusCode::$status; | ||||
|         return Box::new(futures::future::ok(resp)); | ||||
|     }} | ||||
| } | ||||
|  | ||||
| fn handle_api_request<'a>( | ||||
|     info: &'a ApiMethod, parts: Parts, req_body: Body, query: Option<String>) | ||||
|     -> Box<Future<Item = Response<Body>, Error = hyper::Error> + Send + 'a> | ||||
| { | ||||
|  | ||||
| fn handle_request(req: Request<Body>) -> Response<Body> { | ||||
|     let entire_body = req_body.concat2(); | ||||
|  | ||||
|     let resp = entire_body.map(move |body| { | ||||
|         let bytes = match String::from_utf8(body.to_vec()) { // why copy?? | ||||
|             Ok(v) => v, | ||||
|             Err(err) => http_error!(NOT_FOUND, err.to_string()), | ||||
|         }; | ||||
|  | ||||
|         println!("GOT BODY {:?}", parts); | ||||
|  | ||||
|         match parse_query_string(&bytes, &info.parameters, true) { | ||||
|             Ok(res) => { | ||||
|                 let json_str = res.to_string(); | ||||
|                 return Response::new(Body::from(json_str)); | ||||
|             } | ||||
|             Err(err) => { | ||||
|                 http_error!(NOT_FOUND, format!("Method returned error '{:?}'\n", err)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     Box::new(resp) | ||||
| } | ||||
|  | ||||
| fn handle_request(req: Request<Body>) -> BoxFut { | ||||
|  | ||||
|     let (parts, body) = req.into_parts(); | ||||
|  | ||||
|     let method = parts.method.clone(); | ||||
|     let path = parts.uri.path(); | ||||
|     let query = parts.uri.query().map(|x| x.to_owned()); | ||||
|  | ||||
|     let method = req.method(); | ||||
|     let path = req.uri().path(); | ||||
|     let query = req.uri().query(); | ||||
|     let components: Vec<&str> = path.split('/').filter(|x| !x.is_empty()).collect(); | ||||
|     let comp_len = components.len(); | ||||
|  | ||||
| @ -42,25 +91,30 @@ fn handle_request(req: Request<Body>) -> Response<Body> { | ||||
|         if comp_len >= 2 { | ||||
|             let format = components[1]; | ||||
|             if format != "json" { | ||||
|                 http_error!(NOT_FOUND, format!("Unsupported format '{}'\n", format)) | ||||
|                 http_error_future!(NOT_FOUND, format!("Unsupported format '{}'\n", format)) | ||||
|             } | ||||
|  | ||||
|             if let Some(info) = ROUTER.find_method(&components[2..]) { | ||||
|                 println!("FOUND INFO"); | ||||
|                 let api_method_opt = match method { | ||||
|                     &Method::GET => &info.get, | ||||
|                     &Method::PUT => &info.put, | ||||
|                     &Method::POST => &info.post, | ||||
|                     &Method::DELETE => &info.delete, | ||||
|                     Method::GET => &info.get, | ||||
|                     Method::PUT => &info.put, | ||||
|                     Method::POST => &info.post, | ||||
|                     Method::DELETE => &info.delete, | ||||
|                     _ => &None, | ||||
|                 }; | ||||
|                 let api_method = match api_method_opt { | ||||
|                     Some(m) => m, | ||||
|                     _ => http_error!(NOT_FOUND, format!("No such method '{} {}'\n", method, path)), | ||||
|                     _ => http_error_future!(NOT_FOUND, format!("No such method '{} {}'\n", method, path)), | ||||
|                 }; | ||||
|  | ||||
|                 // fixme: handle auth | ||||
|  | ||||
|  | ||||
|                 let res = handle_api_request(api_method, parts, body, query); | ||||
|                 return res; | ||||
|  | ||||
|                 /* | ||||
|                 // extract param | ||||
|                 let param = match query { | ||||
|                     Some(data) => { | ||||
| @ -70,30 +124,36 @@ fn handle_request(req: Request<Body>) -> Response<Body> { | ||||
|                                 let msg = error_list.iter().fold(String::from(""), |acc, item| { | ||||
|                                     acc + &item.to_string() + "\n" | ||||
|                                 }); | ||||
|                                 http_error!(BAD_REQUEST, msg); | ||||
|                                 http_error_future!(BAD_REQUEST, msg); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     None => json!({}), | ||||
|                 }; | ||||
|  | ||||
|  | ||||
|                 /*if body.is_end_stream() { | ||||
|                     println!("NO BODY"); | ||||
|                 }*/ | ||||
|  | ||||
|                 match (api_method.handler)(param, &api_method) { | ||||
|                     Ok(res) => { | ||||
|                         let json_str = res.to_string(); | ||||
|                         return Response::new(Body::from(json_str)); | ||||
|                     } | ||||
|                     Err(err) => { | ||||
|                         http_error!(NOT_FOUND, format!("Method returned error '{}'\n", err)); | ||||
|                         http_error_future!(NOT_FOUND, format!("Method returned error '{}'\n", err)); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
| */ | ||||
|             } else { | ||||
|                 http_error!(NOT_FOUND, format!("No such path '{}'\n", path)); | ||||
|                 http_error_future!(NOT_FOUND, format!("No such path '{}'\n", path)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     Response::new(Body::from("RETURN WEB GUI\n")) | ||||
|     Box::new(future::ok(Response::new(Body::from("RETURN WEB GUI\n")))) | ||||
| } | ||||
|  | ||||
| lazy_static!{ | ||||
| @ -107,7 +167,7 @@ fn main() { | ||||
|  | ||||
|     let new_svc = || { | ||||
|         // service_fn_ok converts our function into a `Service` | ||||
|         service_fn_ok(handle_request) | ||||
|         service_fn(handle_request) | ||||
|     }; | ||||
|  | ||||
|     let server = Server::bind(&addr) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user