extern crate serde; #[macro_use] extern crate serde_json; #[macro_use] extern crate struct2swagger; #[macro_use] extern crate struct2swagger_derive; #[macro_use] extern crate serde_derive; #[macro_use] extern crate slog; use bravery::{error_500, App, EmptyState, Handler, HttpError, Request, Response}; use std::collections::HashMap; use std::env; use std::fs; use std::net::SocketAddr; use struct2swagger::{ swagger_object::{ServerObject, SwaggerObject}, JsonSchemaDefinition, }; #[derive(Serialize, Swagger)] struct JsonStruct { message: String, } #[derive(Clone)] struct TestHandler {} impl Handler for TestHandler { fn invoke(&self, _req: Request) -> Result { let json = JsonStruct { message: "Hello, World!".to_string(), }; let val = serde_json::to_string(&json) .map_err(error_500("Unable to serialize"))? .into_bytes(); Ok(Response { status_code: 200, content_type: Some("application/json".to_string()), body: val, headers: HashMap::new(), }) } } #[derive(Clone)] struct SwaggerHandler { swagger_object: SwaggerObject, } impl Handler for SwaggerHandler { fn invoke(&self, _req: Request) -> Result { let val = serde_json::to_string(&self.swagger_object) .map_err(error_500("Unable to serialize"))? .into_bytes(); Ok(Response { status_code: 200, content_type: Some("application/json".to_string()), body: val, headers: HashMap::new(), }) } } fn get_content_type_from_extension(extension: String) -> Option { match extension.as_ref() { "png" => Some("image/png".to_owned()), "json" => Some("application/json".to_owned()), "map" => Some("application/json".to_owned()), _ => None, } } #[derive(Clone)] struct ServeStaticFile { path_fs: String, mount_path: String, } impl Handler for ServeStaticFile { fn invoke(&self, req: Request) -> Result { let mut request_path = req.path.clone(); if request_path.ends_with('/') { request_path += "index.html"; } request_path.replace_range(0..self.mount_path.len(), &self.path_fs); info!(req.logger, "path"; "req_path" => req.path, "fs_path" => &request_path); let extension_position = &request_path.rfind('.'); let content_type = match extension_position { Some(pos) => { let mut extension = request_path.clone(); extension.replace_range(0..=*pos, ""); info!(req.logger, "path"; "extension" => &extension); get_content_type_from_extension(extension) } None => None, }; let bytes = fs::read(request_path).map_err(error_500("Unable to find path"))?; info!(req.logger, "bytes"; "bytes" => bytes.len()); Ok(Response { status_code: 200, content_type, body: bytes, headers: HashMap::new(), }) } } fn get_app() -> App { let mut swagger_object = struct2swagger::swagger_object::SwaggerObject::new("Swagger example", "1.0.0"); swagger_object.servers = Some(vec![ServerObject { url: "http://localhost:8880".to_string(), description: None, variables: None, }]); let mut app: App = Default::default(); app.get("/", Box::new(TestHandler {})); swagger_add_router!(swagger_object, "GET", "/", 200, "the say!", JsonStruct); app.get( "/swagger-ui*", Box::new(ServeStaticFile { path_fs: "./examples/swagger-ui-dist".to_string(), mount_path: "/swagger-ui".to_string(), }), ); app.get("/openapi.json", Box::new(SwaggerHandler { swagger_object })); app } fn main() -> Result<(), Box> { let addr = env::args() .nth(1) .unwrap_or_else(|| "127.0.0.1:8880".to_string()); let addr = addr.parse::()?; get_app().run(addr)?; Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn swagger() { let app = get_app(); let request = app.create_request("GET", "/", "", b"".to_vec()); let response = app.inject(request); assert_eq!(response.status_code, 200); assert_eq!( response.body, serde_json::to_string(&JsonStruct { message: "Hello, World!" }) .unwrap() ); } }