rouille_maint_in/
lib.rs

1// Copyright (c) 2016 The Rouille developers
2// Licensed under the Apache License, Version 2.0
3// <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
6// at your option. All files in the project carrying such
7// notice may not be copied, modified, or distributed except
8// according to those terms.
9
10//! > <hr>
11//! >
12//! > __NOTE__
13//! >
14//! > This is a maintenace release of rouille, not by its original author, and not endorsed or
15//! > supported by him. The aim of the release is to minimally update the code to the 2018 edition
16//! > of Rust, and upgrade several dependencies to avoid crate duplication. This crate should be
17//! > a drop-in replacement for `rouille-3.0.0`. To use it, update `Cargo.toml` to say:
18//! >
19//! > `rouille = { version = "3", package = "rouille-maint-in" }`
20//! > <hr>
21//!
22//! The rouille library is very easy to get started with.
23//!
24//! Listening to a port is done by calling the [`start_server`](fn.start_server.html) function:
25//!
26//! ```no_run
27//! # use rouille_maint_in as rouille;
28//! use rouille::Request;
29//! use rouille::Response;
30//!
31//! rouille::start_server("0.0.0.0:80", move |request| {
32//!     Response::text("hello world")
33//! });
34//! ```
35//!
36//! Whenever an HTTP request is received on the address passed as first parameter, the closure
37//! passed as second parameter is called. This closure must then return a
38//! [`Response`](struct.Response.html) that will be sent back to the client.
39//!
40//! See the documentation of [`start_server`](fn.start_server.html) for more details.
41//!
42//! # Analyzing the request
43//!
44//! The parameter that the closure receives is a [`Request`](struct.Request.html) object that
45//! represents the request made by the client.
46//!
47//! The `Request` object itself provides some getters, but most advanced functionnalities are
48//! provided by other modules of this crate.
49//!
50//! - In order to dispatch between various code depending on the URL, you can use the
51//!   [`router!`](macro.router.html) macro.
52//! - In order to analyze the body of the request, like handling JSON input, form input, etc. you
53//!   can take a look at [the `input` module](input/index.html).
54//!
55//! # Returning a response
56//!
57//! Once you analyzed the request, it is time to return a response by returning a
58//! [`Response`](struct.Response.html) object.
59//!
60//! All the members of `Response` are public, so you can customize it as you want. There are also
61//! several constructors that you build a basic `Response` which can then modify.
62//!
63//! In order to serve static files, take a look at
64//! [the `match_assets` function](fn.match_assets.html).
65
66#![deny(unsafe_code)]
67
68extern crate base64;
69#[cfg(feature = "brotli2")]
70extern crate brotli2;
71extern crate chrono;
72extern crate filetime;
73#[cfg(feature = "gzip")]
74extern crate deflate;
75extern crate multipart;
76extern crate rand;
77extern crate serde;
78#[macro_use]
79extern crate serde_derive;
80extern crate serde_json;
81extern crate sha1;
82extern crate time;
83extern crate tiny_http;
84pub extern crate url;
85pub extern crate percent_encoding;
86extern crate threadpool;
87extern crate num_cpus;
88
89// https://github.com/servo/rust-url/blob/e121d8d0aafd50247de5f5310a227ecb1efe6ffe/percent_encoding/lib.rs#L126
90pub const DEFAULT_ENCODE_SET: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
91    .add(b' ').add(b'"').add(b'#').add(b'<').add(b'>')
92    .add(b'`').add(b'?').add(b'{').add(b'}');
93
94pub use assets::extension_to_mime;
95pub use assets::match_assets;
96pub use crate::log::{log, log_custom};
97pub use response::{Response, ResponseBody};
98pub use tiny_http::ReadWrite;
99
100use std::time::Duration;
101use std::error::Error;
102use std::io::Cursor;
103use std::io::Result as IoResult;
104use std::io::Read;
105use std::marker::PhantomData;
106use std::net::SocketAddr;
107use std::net::ToSocketAddrs;
108use std::panic;
109use std::panic::AssertUnwindSafe;
110use std::slice::Iter as SliceIter;
111use std::sync::Arc;
112use std::sync::Mutex;
113use std::sync::mpsc;
114use std::thread;
115use std::fmt;
116
117
118pub mod cgi;
119pub mod content_encoding;
120pub mod input;
121pub mod proxy;
122pub mod session;
123pub mod websocket;
124
125mod assets;
126mod find_route;
127mod log;
128mod response;
129mod router;
130#[doc(hidden)]
131pub mod try_or_400;
132
133/// This macro assumes that the current function returns a `Response` and takes a `Result`.
134/// If the expression you pass to the macro is an error, then a 404 response is returned.
135#[macro_export]
136macro_rules! try_or_404 {
137    ($result:expr) => (
138        match $result {
139            Ok(r) => r,
140            Err(_) => return $crate::Response::empty_404(),
141        }
142    );
143}
144
145/// This macro assumes that the current function returns a `Response`. If the condition you pass
146/// to the macro is false, then a 400 response is returned.
147///
148/// # Example
149///
150/// ```
151/// # #[macro_use] extern crate rouille_maint_in as rouille;
152/// # fn main() {
153/// use rouille::Request;
154/// use rouille::Response;
155///
156/// fn handle_something(request: &Request) -> Response {
157///     let data = try_or_400!(post_input!(request, {
158///         field1: u32,
159///         field2: String,
160///     }));
161///
162///     assert_or_400!(data.field1 >= 2);
163///     Response::text("hello")
164/// }
165/// # }
166/// ```
167#[macro_export]
168macro_rules! assert_or_400 {
169    ($cond:expr) => (
170        if !$cond {
171            return $crate::Response::empty_400();
172        }
173    );
174}
175
176/// Calls the [panic!](std::panic!) macro from the standard library wrapped in a
177/// [Response](crate::Response)-typed expression, to avoid the compiler complaining about
178/// unreachable paths in certain styles of `router!` blocks. The macro supports exactly the
179/// same types of arguments as the one in `std`.
180///
181/// # Example
182///
183/// ```should_panic
184/// # #[macro_use] extern crate rouille_maint_in as rouille;
185/// # fn main() {
186/// # use std::net::SocketAddr;
187/// # let request = rouille::Request::fake_http_from("127.0.0.1:60400".parse().expect("socket"), "GET", "/panic", vec![], vec![]);
188/// router!(request,
189///     (GET) (/panic) => {
190///         response_panic!("Oops!");
191///     },
192///     _ => (),
193/// )
194/// # }
195/// ```
196#[macro_export]
197macro_rules! response_panic {
198    () => { $crate::Response::text(if false { "" } else { ::std::panic!(); }) };
199    ($msg:expr $(,)?) => { $crate::Response::text(if false { "" } else { ::std::panic!($msg); }) };
200    ($fmt:expr, $($arg:tt)+) => { $crate::Response::text(if false { "" } else { ::std::panic!($fmt, $($arg)+); }) };
201}
202
203/// Starts a server and uses the given requests handler.
204///
205/// The request handler takes a `&Request` and must return a `Response` to send to the user.
206///
207/// > **Note**: `start_server` is meant to be an easy-to-use function. If you want more control,
208/// > see [the `Server` struct](struct.Server.html).
209///
210/// # Common mistakes
211///
212/// The handler must capture its environment by value and not by reference (`'static`). If you
213/// use closure, don't forget to put `move` in front of the closure.
214///
215/// The handler must also be thread-safe (`Send` and `Sync`).
216/// For example this handler isn't thread-safe:
217///
218/// ```compile_fail
219/// # extern crate rouille_maint_in as rouille;
220/// let mut requests_counter = 0;
221///
222/// rouille::start_server("localhost:80", move |request| {
223///     requests_counter += 1;
224///
225///     // ... rest of the handler ...
226/// # panic!()
227/// })
228/// ```
229///
230/// Multiple requests can be processed simultaneously, therefore you can't mutably access
231/// variables from the outside.
232///
233/// Instead you must use a `Mutex`:
234///
235/// ```no_run
236/// # use rouille_maint_in as rouille;
237/// use std::sync::Mutex;
238/// let requests_counter = Mutex::new(0);
239///
240/// rouille::start_server("localhost:80", move |request| {
241///     *requests_counter.lock().unwrap() += 1;
242///
243///     // rest of the handler
244/// # panic!()
245/// })
246/// ```
247///
248/// # Panic handling in the handler
249///
250/// If your request handler panicks, a 500 error will automatically be sent to the client.
251///
252/// # Panic
253///
254/// This function will panic if the server starts to fail (for example if you use a port that is
255/// already occupied) or if the socket is force-closed by the operating system.
256///
257/// If you need to handle these situations, please see `Server`.
258pub fn start_server<A, F>(addr: A, handler: F) -> !
259                          where A: ToSocketAddrs,
260                                F: Send + Sync + 'static + Fn(&Request) -> Response
261{
262    Server::new(addr, handler).expect("Failed to start server").run();
263    panic!("The server socket closed unexpectedly")
264}
265
266
267/// Identical to `start_server` but uses a `ThreadPool` of the given size.
268///
269/// When `pool_size` is `None`, the thread pool size will default to `8 * num-cpus`.
270/// `pool_size` must be greater than zero or this function will panic.
271pub fn start_server_with_pool<A, F>(addr: A, pool_size: Option<usize>, handler: F) -> !
272                          where A: ToSocketAddrs,
273                                F: Send + Sync + 'static + Fn(&Request) -> Response
274{
275    Server::new(addr, handler).expect("Failed to start server")
276        .pool_size(pool_size.unwrap_or_else(|| 8 * num_cpus::get()))
277        .run();
278    panic!("The server socket closed unexpectedly")
279}
280
281
282/// Executes a function in either a thread of a thread pool
283enum Executor {
284    Threaded,
285    Pooled {
286        pool: threadpool::ThreadPool,
287    }
288}
289impl Executor {
290    /// `size` must be greater than zero or the call to `ThreadPool::new` will panic.
291    fn with_size(size: usize) -> Self {
292        let pool = threadpool::ThreadPool::new(size);
293        Executor::Pooled { pool }
294    }
295
296    #[inline]
297    fn execute<F: FnOnce() + Send + 'static>(&self, f: F) {
298        match *self {
299            Executor::Threaded => { thread::spawn(f); }
300            Executor::Pooled { ref pool } => { pool.execute(f); }
301        }
302    }
303}
304
305
306/// A listening server.
307///
308/// This struct is the more manual server creation API of rouille and can be used as an alternative
309/// to the `start_server` function.
310///
311/// The `start_server` function is just a shortcut for `Server::new` followed with `run`. See the
312/// documentation of the `start_server` function for more details about the handler.
313///
314/// # Example
315///
316/// ```no_run
317/// # use rouille_maint_in as rouille;
318/// use rouille::Server;
319/// use rouille::Response;
320///
321/// let server = Server::new("localhost:0", |request| {
322///     Response::text("hello world")
323/// }).unwrap();
324/// println!("Listening on {:?}", server.server_addr());
325/// server.run();
326/// ```
327pub struct Server<F> {
328    server: tiny_http::Server,
329    handler: Arc<AssertUnwindSafe<F>>,
330    executor: Executor,
331}
332
333
334impl<F> Server<F> where F: Send + Sync + 'static + Fn(&Request) -> Response {
335    /// Builds a new `Server` object.
336    ///
337    /// After this function returns, the HTTP server is listening.
338    ///
339    /// Returns an error if there was an error while creating the listening socket, for example if
340    /// the port is already in use.
341    pub fn new<A>(addr: A, handler: F) -> Result<Server<F>, Box<dyn Error + Send + Sync>>
342        where A: ToSocketAddrs
343    {
344        let server = tiny_http::Server::http(addr)?;
345        Ok(Server {
346            server,
347            executor: Executor::Threaded,
348            handler: Arc::new(AssertUnwindSafe(handler)),   // TODO: using AssertUnwindSafe here is wrong, but unwind safety has some usability problems in Rust in general
349        })
350    }
351
352    /// Builds a new `Server` object with SSL support.
353    ///
354    /// After this function returns, the HTTPS server is listening.
355    ///
356    /// Returns an error if there was an error while creating the listening socket, for example if
357    /// the port is already in use.
358    #[cfg(feature = "ssl")]
359    pub fn new_ssl<A>(
360        addr: A,
361        handler: F,
362        certificate: Vec<u8>,
363        private_key: Vec<u8>,
364    ) -> Result<Server<F>, Box<dyn Error + Send + Sync>> where A: ToSocketAddrs {
365        let ssl_config = tiny_http::SslConfig {
366            certificate,
367            private_key,
368        };
369        let server = tiny_http::Server::https(addr, ssl_config)?;
370        Ok(Server {
371            server,
372            executor: Executor::Threaded,
373            handler: Arc::new(AssertUnwindSafe(handler)),   // TODO: using AssertUnwindSafe here is wrong, but unwind safety has some usability problems in Rust in general
374        })
375    }
376
377    /// Use a `ThreadPool` of the given size to process requests
378    ///
379    /// `pool_size` must be greater than zero or this function will panic.
380    pub fn pool_size(mut self, pool_size: usize) -> Self {
381        self.executor = Executor::with_size(pool_size);
382        self
383    }
384
385    /// Returns the address of the listening socket.
386    #[inline]
387    pub fn server_addr(&self) -> SocketAddr {
388        self.server.server_addr()
389    }
390
391    /// Runs the server forever, or until the listening socket is somehow force-closed by the
392    /// operating system.
393    #[inline]
394    pub fn run(self) {
395        for request in self.server.incoming_requests() {
396            self.process(request);
397        }
398    }
399
400    /// Processes all the client requests waiting to be processed, then returns.
401    ///
402    /// This function executes very quickly, as each client requests that needs to be processed
403    /// is processed in a separate thread.
404    #[inline]
405    pub fn poll(&self) {
406        while let Ok(Some(request)) = self.server.try_recv() {
407            self.process(request);
408        }
409    }
410
411    /// Creates a new thread for the server that can be gracefully stopped later.
412    ///
413    /// This function returns a tuple of a `JoinHandle` and a `Sender`.
414    /// You must call `JoinHandle::join()` otherwise the server will not run until completion.
415    /// The server can be stopped at will by sending it an empty `()` message from another thread.
416    /// There may be a maximum of a 1 second delay between sending the stop message and the server
417    /// stopping. This delay may be shortened in future.
418    ///
419    /// ```no_run
420    /// # use rouille_maint_in as rouille;
421    /// use std::thread;
422    /// use std::time::Duration;
423    /// use rouille::Server;
424    /// use rouille::Response;
425    ///
426    /// let server = Server::new("localhost:0", |request| {
427    ///     Response::text("hello world")
428    /// }).unwrap();
429    /// println!("Listening on {:?}", server.server_addr());
430    /// let (handle, sender) = server.stoppable();
431    ///
432    /// // Stop the server in 3 seconds
433    /// thread::spawn(move || {
434    ///     thread::sleep(Duration::from_secs(3));
435    ///     sender.send(()).unwrap();
436    /// });
437    ///
438    /// // Block the main thread until the server is stopped
439    /// handle.join().unwrap();
440    /// ```
441    #[inline]
442    pub fn stoppable(self) -> (thread::JoinHandle<()>, mpsc::Sender<()>) {
443        let (tx, rx) = mpsc::channel();
444        let handle = thread::spawn(move || {
445            while let Err(_) = rx.try_recv() {
446                // In order to reduce CPU load wait 1s for a recv before looping again
447                while let Ok(Some(request)) = self.server.recv_timeout(Duration::from_secs(1)) {
448                    self.process(request);
449                }
450            }
451        });
452
453        (handle, tx)
454    }
455
456    /// Same as `poll()` but blocks for at most `duration` before returning.
457    ///
458    /// This function can be used implement a custom server loop in a more CPU-efficient manner
459    /// than calling `poll`.
460    ///
461    /// # Example
462    ///
463    /// ```no_run
464    /// # use rouille_maint_in as rouille;
465    /// use rouille::Server;
466    /// use rouille::Response;
467    ///
468    /// let server = Server::new("localhost:0", |request| {
469    ///     Response::text("hello world")
470    /// }).unwrap();
471    /// println!("Listening on {:?}", server.server_addr());
472    ///
473    /// loop {
474    ///     server.poll_timeout(std::time::Duration::from_millis(100));
475    /// }
476    /// ```
477    #[inline]
478    pub fn poll_timeout(&self, dur: std::time::Duration) {
479        while let Ok(Some(request)) = self.server.recv_timeout(dur) {
480            self.process(request);
481        }
482    }
483
484    // Internal function, called when we got a request from tiny-http that needs to be processed.
485    fn process(&self, request: tiny_http::Request) {
486        // We spawn a thread so that requests are processed in parallel.
487        let handler = self.handler.clone();
488        self.executor.execute(|| {
489            // Small helper struct that makes it possible to put
490            // a `tiny_http::Request` inside a `Box<Read>`.
491            struct RequestRead(Arc<Mutex<Option<tiny_http::Request>>>);
492            impl Read for RequestRead {
493                #[inline]
494                fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
495                    self.0.lock().unwrap().as_mut().unwrap().as_reader().read(buf)
496                }
497            }
498
499            // Building the `Request` object.
500            let tiny_http_request;
501            let rouille_request = {
502                let url = request.url().to_owned();
503                let method = request.method().as_str().to_owned();
504                let headers = request.headers().iter().map(|h| (h.field.to_string(), h.value.clone().into())).collect();
505                let remote_addr = *request.remote_addr();
506
507                tiny_http_request = Arc::new(Mutex::new(Some(request)));
508                let data = Arc::new(Mutex::new(Some(Box::new(RequestRead(tiny_http_request.clone())) as Box<_>)));
509
510                Request {
511                    url,
512                    method,
513                    headers,
514                    https: false,
515                    data,
516                    remote_addr,
517                }
518            };
519
520            // Calling the handler ; this most likely takes a lot of time.
521            // If the handler panics, we build a dummy response.
522            let mut rouille_response = {
523                // We don't use the `rouille_request` anymore after the panic, so it's ok to assert
524                // it's unwind safe.
525                let rouille_request = AssertUnwindSafe(rouille_request);
526                let res = panic::catch_unwind(move || {
527                    let rouille_request = rouille_request;
528                    handler(&rouille_request)
529                });
530
531                match res {
532                    Ok(r) => r,
533                    Err(_) => {
534                        Response::html("<h1>Internal Server Error</h1>\
535                                        <p>An internal error has occurred on the server.</p>")
536                            .with_status_code(500)
537                    }
538                }
539            };
540
541            // writing the response
542            let (res_data, res_len) = rouille_response.data.into_reader_and_size();
543            let mut response = tiny_http::Response::empty(rouille_response.status_code)
544                                            .with_data(res_data, res_len);
545
546            let mut upgrade_header = "".into();
547
548            for (key, value) in rouille_response.headers {
549                if key.eq_ignore_ascii_case("Content-Length") {
550                    continue;
551                }
552
553                if key.eq_ignore_ascii_case("Upgrade") {
554                    upgrade_header = value;
555                    continue;
556                }
557
558                if let Ok(header) = tiny_http::Header::from_bytes(key.as_bytes(), value.as_bytes()) {
559                    response.add_header(header);
560                } else {
561                    // TODO: ?
562                }
563            }
564
565            if let Some(ref mut upgrade) = rouille_response.upgrade {
566                let trq = tiny_http_request.lock().unwrap().take().unwrap();
567                let socket = trq.upgrade(&upgrade_header, response);
568                upgrade.build(socket);
569
570            } else {
571                // We don't really care if we fail to send the response to the client, as there's
572                // nothing we can do anyway.
573                let _ = tiny_http_request.lock().unwrap().take().unwrap().respond(response);
574            }
575        });
576    }
577}
578
579/// Trait for objects that can take ownership of a raw connection to the client data.
580///
581/// The purpose of this trait is to be used with the `Connection: Upgrade` header, hence its name.
582pub trait Upgrade {
583    /// Initializes the object with the given socket.
584    fn build(&mut self, socket: Box<dyn ReadWrite + Send>);
585}
586
587/// Represents a request that your handler must answer to.
588///
589/// This can be either a real request (received by the HTTP server) or a mock object created with
590/// one of the `fake_*` constructors.
591pub struct Request {
592    method: String,
593    url: String,
594    headers: Vec<(String, String)>,
595    https: bool,
596    data: Arc<Mutex<Option<Box<dyn Read + Send>>>>,
597    remote_addr: SocketAddr,
598}
599
600impl fmt::Debug for Request {
601    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
602        f.debug_struct("Request")
603            .field("method", &self.method)
604            .field("url", &self.url)
605            .field("headers", &self.headers)
606            .field("https", &self.https)
607            .field("remote_addr", &self.remote_addr)
608            .finish()
609    }
610}
611
612impl Request {
613    /// Builds a fake HTTP request to be used during tests.
614    ///
615    /// The remote address of the client will be `127.0.0.1:12345`. Use `fake_http_from` to
616    /// specify what the client's address should be.
617    pub fn fake_http<U, M>(method: M, url: U, headers: Vec<(String, String)>, data: Vec<u8>)
618                           -> Request where U: Into<String>, M: Into<String>
619    {
620        let data = Arc::new(Mutex::new(Some(Box::new(Cursor::new(data)) as Box<_>)));
621        let remote_addr = "127.0.0.1:12345".parse().unwrap();
622
623        Request {
624            url: url.into(),
625            method: method.into(),
626            https: false,
627            data,
628            headers,
629            remote_addr,
630        }
631    }
632
633    /// Builds a fake HTTP request to be used during tests.
634    pub fn fake_http_from<U, M>(from: SocketAddr, method: M, url: U,
635                                headers: Vec<(String, String)>, data: Vec<u8>)
636                                -> Request where U: Into<String>, M: Into<String>
637    {
638        let data = Arc::new(Mutex::new(Some(Box::new(Cursor::new(data)) as Box<_>)));
639
640        Request {
641            url: url.into(),
642            method: method.into(),
643            https: false,
644            data,
645            headers,
646            remote_addr: from,
647        }
648    }
649
650    /// Builds a fake HTTPS request to be used during tests.
651    ///
652    /// The remote address of the client will be `127.0.0.1:12345`. Use `fake_https_from` to
653    /// specify what the client's address should be.
654    pub fn fake_https<U, M>(method: M, url: U, headers: Vec<(String, String)>, data: Vec<u8>)
655                            -> Request where U: Into<String>, M: Into<String>
656    {
657        let data = Arc::new(Mutex::new(Some(Box::new(Cursor::new(data)) as Box<_>)));
658        let remote_addr = "127.0.0.1:12345".parse().unwrap();
659
660        Request {
661            url: url.into(),
662            method: method.into(),
663            https: true,
664            data,
665            headers,
666            remote_addr,
667        }
668    }
669
670    /// Builds a fake HTTPS request to be used during tests.
671    pub fn fake_https_from<U, M>(from: SocketAddr, method: M, url: U,
672                                 headers: Vec<(String, String)>, data: Vec<u8>)
673                                 -> Request where U: Into<String>, M: Into<String>
674    {
675        let data = Arc::new(Mutex::new(Some(Box::new(Cursor::new(data)) as Box<_>)));
676
677        Request {
678            url: url.into(),
679            method: method.into(),
680            https: true,
681            data,
682            headers,
683            remote_addr: from,
684        }
685    }
686
687    /// If the decoded URL of the request starts with `prefix`, builds a new `Request` that is
688    /// the same as the original but without that prefix.
689    ///
690    /// # Example
691    ///
692    /// ```
693    /// # use rouille_maint_in as rouille;
694    /// # use rouille::Request;
695    /// # use rouille::Response;
696    /// fn handle(request: &Request) -> Response {
697    ///     if let Some(request) = request.remove_prefix("/static") {
698    ///         return rouille::match_assets(&request, "/static");
699    ///     }
700    ///
701    ///     // ...
702    ///     # panic!()
703    /// }
704    /// ```
705    pub fn remove_prefix(&self, prefix: &str) -> Option<Request> {
706        if !self.url().starts_with(prefix) {
707            return None;
708        }
709
710        // TODO: url-encoded characters in the prefix are not implemented
711        assert!(self.url.starts_with(prefix));
712        Some(Request {
713            method: self.method.clone(),
714            url: self.url[prefix.len() ..].to_owned(),
715            headers: self.headers.clone(),      // TODO: expensive
716            https: self.https,
717            data: self.data.clone(),
718            remote_addr: self.remote_addr,
719        })
720    }
721
722    /// Returns `true` if the request uses HTTPS, and `false` if it uses HTTP.
723    ///
724    /// # Example
725    ///
726    /// ```
727    /// # use rouille_maint_in as rouille;
728    /// use rouille::{Request, Response};
729    ///
730    /// fn handle(request: &Request) -> Response {
731    ///     if !request.is_secure() {
732    ///         return Response::redirect_303(format!("https://example.com"));
733    ///     }
734    ///
735    ///     // ...
736    /// # panic!()
737    /// }
738    /// ```
739    #[inline]
740    pub fn is_secure(&self) -> bool {
741        self.https
742    }
743
744    /// Returns the method of the request (`GET`, `POST`, etc.).
745    #[inline]
746    pub fn method(&self) -> &str {
747        &self.method
748    }
749
750    /// Returns the raw URL requested by the client. It is not decoded and thus can contain strings
751    /// such as `%20`, and the query parameters such as `?p=hello`.
752    ///
753    /// See also `url()`.
754    ///
755    /// # Example
756    ///
757    /// ```
758    /// # use rouille_maint_in as rouille;
759    /// use rouille::Request;
760    ///
761    /// let request = Request::fake_http("GET", "/hello%20world?foo=bar", vec![], vec![]);
762    /// assert_eq!(request.raw_url(), "/hello%20world?foo=bar");
763    /// ```
764    #[inline]
765    pub fn raw_url(&self) -> &str {
766        &self.url
767    }
768
769    /// Returns the raw query string requested by the client. In other words, everything after the
770    /// first `?` in the raw url.
771    ///
772    /// Returns the empty string if no query string.
773    #[inline]
774    pub fn raw_query_string(&self) -> &str {
775        if let Some(pos) = self.url.bytes().position(|c| c == b'?') {
776            self.url.split_at(pos + 1).1
777        } else {
778            ""
779        }
780    }
781
782    /// Returns the URL requested by the client.
783    ///
784    /// Contrary to `raw_url`, special characters have been decoded and the query string
785    /// (eg `?p=hello`) has been removed.
786    ///
787    /// If there is any non-unicode character in the URL, it will be replaced with `U+FFFD`.
788    ///
789    /// > **Note**: This function will decode the token `%2F` will be decoded as `/`. However the
790    /// > official speficiations say that such a token must not count as a delimiter for URL paths.
791    /// > In other words, `/hello/world` is not the same as `/hello%2Fworld`.
792    ///
793    /// # Example
794    ///
795    /// ```
796    /// # use rouille_maint_in as rouille;
797    /// use rouille::Request;
798    ///
799    /// let request = Request::fake_http("GET", "/hello%20world?foo=bar", vec![], vec![]);
800    /// assert_eq!(request.url(), "/hello world");
801    /// ```
802    pub fn url(&self) -> String {
803        let url = self.url.as_bytes();
804        let url = if let Some(pos) = url.iter().position(|&c| c == b'?') {
805            &url[..pos]
806        } else {
807            url
808        };
809
810        percent_encoding::percent_decode(url).decode_utf8_lossy().into_owned()
811    }
812
813    /// Returns the value of a GET parameter.
814    /// TODO: clumbsy
815    pub fn get_param(&self, param_name: &str) -> Option<String> {
816        let get_params = self.raw_query_string();
817
818        // TODO: `hello=5` will be matched for param name `lo`
819
820        let param = match get_params.rfind(&format!("{}=", param_name)) {
821            Some(p) => p + param_name.len() + 1,
822            None => return None,
823        };
824
825        let value = match get_params.bytes().skip(param).position(|c| c == b'&') {
826            None => &get_params[param..],
827            Some(e) => &get_params[param .. e + param],
828        };
829
830        Some(percent_encoding::percent_decode(value.replace("+", " ").as_bytes()).decode_utf8_lossy().into_owned())
831    }
832
833    /// Returns the value of a header of the request.
834    ///
835    /// Returns `None` if no such header could be found.
836    #[inline]
837    pub fn header(&self, key: &str) -> Option<&str> {
838        self.headers.iter().find(|&&(ref k, _)| k.eq_ignore_ascii_case(key)).map(|&(_, ref v)| &v[..])
839    }
840
841    /// Returns a list of all the headers of the request.
842    #[inline]
843    pub fn headers(&self) -> HeadersIter {
844        HeadersIter { iter: self.headers.iter() }
845    }
846
847    /// Returns the state of the `DNT` (Do Not Track) header.
848    ///
849    /// If the header is missing or is malformed, `None` is returned. If the header exists,
850    /// `Some(true)` is returned if `DNT` is `1` and `Some(false)` is returned if `DNT` is `0`.
851    ///
852    /// # Example
853    ///
854    /// ```
855    /// # use rouille_maint_in as rouille;
856    /// use rouille::{Request, Response};
857    ///
858    /// # fn track_user(request: &Request) {}
859    /// fn handle(request: &Request) -> Response {
860    ///     if !request.do_not_track().unwrap_or(false) {
861    ///         track_user(&request);
862    ///     }
863    ///
864    ///     // ...
865    /// # panic!()
866    /// }
867    /// ```
868    pub fn do_not_track(&self) -> Option<bool> {
869        match self.header("DNT") {
870            Some(h) if h == "1" => Some(true),
871            Some(h) if h == "0" => Some(false),
872            _ => None
873        }
874    }
875
876    /// Returns the body of the request.
877    ///
878    /// The body can only be retrieved once. Returns `None` is the body has already been retreived
879    /// before.
880    ///
881    /// # Example
882    ///
883    /// ```
884    /// # use rouille_maint_in as rouille;
885    /// use std::io::Read;
886    /// use rouille::{Request, Response, ResponseBody};
887    ///
888    /// fn echo(request: &Request) -> Response {
889    ///     let mut data = request.data().expect("Oops, body already retrieved, problem \
890    ///                                           in the server");
891    ///
892    ///     let mut buf = Vec::new();
893    ///     match data.read_to_end(&mut buf) {
894    ///         Ok(_) => (),
895    ///         Err(_) => return Response::text("Failed to read body")
896    ///     };
897    ///
898    ///     Response {
899    ///         data: ResponseBody::from_data(buf),
900    ///         .. Response::text("")
901    ///     }
902    /// }
903    /// ```
904    pub fn data(&self) -> Option<RequestBody> {
905        let reader = self.data.lock().unwrap().take();
906        reader.map(|r| RequestBody { body: r, marker: PhantomData })
907    }
908
909    /// Returns the address of the client that made this request.
910    ///
911    /// # Example
912    ///
913    /// ```
914    /// # use rouille_maint_in as rouille;
915    /// use rouille::{Request, Response};
916    ///
917    /// fn handle(request: &Request) -> Response {
918    ///     Response::text(format!("Your IP is: {:?}", request.remote_addr()))
919    /// }
920    /// ```
921    #[inline]
922    pub fn remote_addr(&self) -> &SocketAddr {
923        &self.remote_addr
924    }
925}
926
927/// Iterator to the list of headers in a request.
928#[derive(Debug, Clone)]
929pub struct HeadersIter<'a> {
930    iter: SliceIter<'a, (String, String)>
931}
932
933impl<'a> Iterator for HeadersIter<'a> {
934    type Item = (&'a str, &'a str);
935
936    #[inline]
937    fn next(&mut self) -> Option<Self::Item> {
938        self.iter.next().map(|&(ref k, ref v)| (&k[..], &v[..]))
939    }
940
941    #[inline]
942    fn size_hint(&self) -> (usize, Option<usize>) {
943        self.iter.size_hint()
944    }
945}
946
947impl<'a> ExactSizeIterator for HeadersIter<'a> {
948}
949
950/// Gives access to the body of a request.
951///
952/// In order to obtain this object, call `request.data()`.
953pub struct RequestBody<'a> {
954    body: Box<dyn Read + Send>,
955    marker: PhantomData<&'a ()>,
956}
957
958impl<'a> Read for RequestBody<'a> {
959    #[inline]
960    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
961        self.body.read(buf)
962    }
963}
964
965#[cfg(test)]
966mod tests {
967    use crate::Request;
968
969    #[test]
970    fn header() {
971        let request = Request::fake_http("GET", "/", vec![("Host".to_owned(), "localhost".to_owned())], vec![]);
972        assert_eq!(request.header("Host"), Some("localhost"));
973        assert_eq!(request.header("host"), Some("localhost"));
974    }
975
976    #[test]
977    fn get_param() {
978        let request = Request::fake_http("GET", "/?p=hello", vec![], vec![]);
979        assert_eq!(request.get_param("p"), Some("hello".to_owned()));
980    }
981
982    #[test]
983    fn body_twice() {
984        let request = Request::fake_http("GET", "/", vec![], vec![62, 62, 62]);
985        assert!(request.data().is_some());
986        assert!(request.data().is_none());
987    }
988
989    #[test]
990    fn url_strips_get_query() {
991        let request = Request::fake_http("GET", "/?p=hello", vec![], vec![]);
992        assert_eq!(request.url(), "/");
993    }
994
995    #[test]
996    fn urlencode_query_string() {
997        let request = Request::fake_http("GET", "/?p=hello%20world", vec![], vec![]);
998        assert_eq!(request.get_param("p"), Some("hello world".to_owned()));
999    }
1000
1001    #[test]
1002    fn plus_in_query_string() {
1003        let request = Request::fake_http("GET", "/?p=hello+world", vec![], vec![]);
1004        assert_eq!(request.get_param("p"), Some("hello world".to_owned()));
1005    }
1006
1007    #[test]
1008    fn encoded_plus_in_query_string() {
1009        let request = Request::fake_http("GET", "/?p=hello%2Bworld", vec![], vec![]);
1010        assert_eq!(request.get_param("p"), Some("hello+world".to_owned()));
1011    }
1012
1013    #[test]
1014    fn url_encode() {
1015        let request = Request::fake_http("GET", "/hello%20world", vec![], vec![]);
1016        assert_eq!(request.url(), "/hello world");
1017    }
1018
1019    #[test]
1020    fn plus_in_url() {
1021        let request = Request::fake_http("GET", "/hello+world", vec![], vec![]);
1022        assert_eq!(request.url(), "/hello+world");
1023    }
1024
1025    #[test]
1026    fn dnt() {
1027        let request = Request::fake_http("GET", "/", vec![("DNT".to_owned(), "1".to_owned())], vec![]);
1028        assert_eq!(request.do_not_track(), Some(true));
1029
1030        let request = Request::fake_http("GET", "/", vec![("DNT".to_owned(), "0".to_owned())], vec![]);
1031        assert_eq!(request.do_not_track(), Some(false));
1032
1033        let request = Request::fake_http("GET", "/", vec![], vec![]);
1034        assert_eq!(request.do_not_track(), None);
1035
1036        let request = Request::fake_http("GET", "/", vec![("DNT".to_owned(), "malformed".to_owned())], vec![]);
1037        assert_eq!(request.do_not_track(), None);
1038    }
1039}