1 extern crate tiny_http;
2 extern crate multipart;
3 
4 use std::io::{self, Cursor, Write};
5 use multipart::server::{Multipart, Entries, SaveResult};
6 use multipart::mock::StdoutTee;
7 use tiny_http::{Response, StatusCode, Request};
main()8 fn main() {
9     // Starting a server on `localhost:80`
10     let server = tiny_http::Server::http("localhost:80").expect("Could not bind localhost:80");
11     loop {
12         // This blocks until the next request is received
13         let mut request = server.recv().unwrap();
14 
15         // Processes a request and returns response or an occured error
16         let result = process_request(&mut request);
17         let resp = match result {
18             Ok(resp) => resp,
19             Err(e) => {
20                 println!("An error has occured during request proccessing: {:?}", e);
21                 build_response(500, "The received data was not correctly proccessed on the server")
22             }
23         };
24 
25         // Answers with a response to a client
26         request.respond(resp).unwrap();
27     }
28 }
29 
30 type RespBody = Cursor<Vec<u8>>;
31 
32 /// Processes a request and returns response or an occured error.
process_request(request: &mut Request) -> io::Result<Response<RespBody>>33 fn process_request(request: &mut Request) -> io::Result<Response<RespBody>> {
34     // Getting a multipart reader wrapper
35     match Multipart::from_request(request) {
36         Ok(mut multipart) => {
37             // Fetching all data and processing it.
38             // save().temp() reads the request fully, parsing all fields and saving all files
39             // in a new temporary directory under the OS temporary directory.
40             match multipart.save().temp() {
41                 SaveResult::Full(entries) => process_entries(entries),
42                 SaveResult::Partial(entries, reason) => {
43                     process_entries(entries.keep_partial())?;
44                     // We don't set limits
45                     Err(reason.unwrap_err())
46                 }
47                 SaveResult::Error(error) => Err(error),
48             }
49         }
50         Err(_) => Ok(build_response(400, "The request is not multipart")),
51     }
52 }
53 
54 /// Processes saved entries from multipart request.
55 /// Returns an OK response or an error.
process_entries(entries: Entries) -> io::Result<Response<RespBody>>56 fn process_entries(entries: Entries) -> io::Result<Response<RespBody>> {
57     let mut data = Vec::new();
58 
59     {
60         let stdout = io::stdout();
61         let tee = StdoutTee::new(&mut data, &stdout);
62         entries.write_debug(tee)?;
63     }
64 
65     writeln!(data, "Entries processed")?;
66 
67     Ok(build_response(200, data))
68 }
69 
build_response<D: Into<Vec<u8>>>(status_code: u16, data: D) -> Response<RespBody>70 fn build_response<D: Into<Vec<u8>>>(status_code: u16, data: D) -> Response<RespBody> {
71     let data = data.into();
72     let data_len = data.len();
73     Response::new(StatusCode(status_code),
74                   vec![],
75                   Cursor::new(data),
76                   Some(data_len),
77                   None)
78 }
79