| 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) |
| } |