| extern crate tiny_http; | |
| extern crate multipart; | |
| use std::io::{self, Cursor, Write}; | |
| use multipart::server::{Multipart, Entries, SaveResult}; | |
| use multipart::mock::StdoutTee; | |
| use tiny_http::{Response, StatusCode, Request}; | |
| fn main() { | |
| // Starting a server on `localhost:80` | |
| let server = tiny_http::Server::http("localhost:80").expect("Could not bind localhost:80"); | |
| loop { | |
| // This blocks until the next request is received | |
| let mut request = server.recv().unwrap(); | |
| // Processes a request and returns response or an occured error | |
| let result = process_request(&mut request); | |
| let resp = match result { | |
| Ok(resp) => resp, | |
| Err(e) => { | |
| println!("An error has occured during request proccessing: {:?}", e); | |
| build_response(500, "The received data was not correctly proccessed on the server") | |
| } | |
| }; | |
| // Answers with a response to a client | |
| request.respond(resp).unwrap(); | |
| } | |
| } | |
| type RespBody = Cursor<Vec<u8>>; | |
| /// Processes a request and returns response or an occured error. | |
| fn process_request(request: &mut Request) -> io::Result<Response<RespBody>> { | |
| // Getting a multipart reader wrapper | |
| match Multipart::from_request(request) { | |
| Ok(mut multipart) => { | |
| // Fetching all data and processing it. | |
| // save().temp() reads the request fully, parsing all fields and saving all files | |
| // in a new temporary directory under the OS temporary directory. | |
| match multipart.save().temp() { | |
| SaveResult::Full(entries) => process_entries(entries), | |
| SaveResult::Partial(entries, reason) => { | |
| process_entries(entries.keep_partial())?; | |
| // We don't set limits | |
| Err(reason.unwrap_err()) | |
| } | |
| SaveResult::Error(error) => Err(error), | |
| } | |
| } | |
| Err(_) => Ok(build_response(400, "The request is not multipart")), | |
| } | |
| } | |
| /// Processes saved entries from multipart request. | |
| /// Returns an OK response or an error. | |
| fn process_entries(entries: Entries) -> io::Result<Response<RespBody>> { | |
| let mut data = Vec::new(); | |
| { | |
| let stdout = io::stdout(); | |
| let tee = StdoutTee::new(&mut data, &stdout); | |
| entries.write_debug(tee)?; | |
| } | |
| writeln!(data, "Entries processed")?; | |
| Ok(build_response(200, data)) | |
| } | |
| fn build_response<D: Into<Vec<u8>>>(status_code: u16, data: D) -> Response<RespBody> { | |
| let data = data.into(); | |
| let data_len = data.len(); | |
| Response::new(StatusCode(status_code), | |
| vec![], | |
| Cursor::new(data), | |
| Some(data_len), | |
| None) | |
| } |