Struct Request

Source
pub struct Request {
    pub method: Method,
    pub path: String,
    pub version: String,
    pub query: Query,
    pub headers: Headers,
    pub cookies: CookieJar,
    pub body: Arc<Vec<u8>>,
    pub address: SocketAddr,
    pub socket: Arc<Mutex<TcpStream>>,
    /* private fields */
}
Expand description

Http Request

Fieldsยง

ยงmethod: Method

Request method.

ยงpath: String

Request path (not tokenized). The query string is not included, its in the query field.

ยงversion: String

HTTP version string. Should usually be โ€œHTTP/1.1โ€.

ยงquery: Query

Request Query.

ยงheaders: Headers

Request headers. Will not include cookies, which are in the cookies field.

ยงcookies: CookieJar

Request Cookies.

ยงbody: Arc<Vec<u8>>

Request body, as a static byte vec.

ยงaddress: SocketAddr

Client socket address. If you are using a reverse proxy, this will be the address of the proxy (often localhost).

ยงsocket: Arc<Mutex<TcpStream>>

The raw tcp socket

Implementationsยง

Sourceยง

impl Request

Source

pub fn param(&self, name: impl AsRef<str>) -> Option<String>

Get a path parameter by its name.

ยงExample
server.route(Method::GET, "/greet/{name}", |req| {
    // Get name Path param
    // This is safe to unwrap because the router will only call this handler if the path param exists
    let name = req.param("name").unwrap();

    // Format a nice message
    let message = format!("Hello, {}", name);

    // Send Response
    Response::new()
        .text(message)
        .content(Content::TXT)
});
Examples found in repository?
examples/basic/path_prams.rs (line 25)
16    fn exec(&self) {
17        // Create a new Server instance on localhost port 8080
18        let mut server: Server = Server::<()>::new("localhost", 8081);
19
20        // Define a handler for GET "/greet/{name}"
21        // This will handel requests with anything where the {name} is
22        // This includes "/greet/bob", "/greet/fin"
23        server.route(Method::GET, "/greet/{name}", |req| {
24            // Get name path param
25            let name = req.param("name").unwrap();
26
27            // Make a nice Message to send
28            let message = format!("Hello, {}", name);
29
30            // Send Response
31            Response::new().text(message).content(Content::TXT)
32        });
33
34        // Define a greet route for Darren because he is very cool
35        // This will take priority over the other route as it is defined after
36        server.route(Method::GET, "/greet/Darren/", |_req| {
37            Response::new().text("Hello, Darren. You are very cool")
38        });
39
40        // Start the server
41        // This will block the current thread
42        server.start().unwrap();
43    }
More examples
Hide additional examples
examples/basic/data.rs (line 74)
18    fn exec(&self) {
19        // Create a new Server instance on localhost port 8080
20        let mut server = Server::<()>::new(Ipv4Addr::LOCALHOST, 8080);
21
22        // Define a route to handel query string
23        // This will try to find a name value pair in the query string
24        server.route(Method::GET, "/", |req| {
25            // Format the response text
26            let text = format!(
27                "<h1>Hello, {}!</h1>",
28                // Get the query value of name and default to "Nobody" if not found
29                req.query.get("name").unwrap_or("Nobody")
30            );
31
32            Response::new().text(text).content(Content::HTML)
33        });
34
35        // Define another route
36        // This time to handle form data
37        server.route(Method::POST, "/form", |req| {
38            // The body of requests is not part of the req.query
39            // Instead it is part of the req.body but as a string
40            // We will need to parse it get it as a query
41            let body_data = Query::from_body(&String::from_utf8_lossy(&req.body));
42
43            let name = body_data.get("name").unwrap_or("Nobody");
44            let text = format!("<h1>Hello, {}</h1>", name);
45
46            // Create a new response, with the following default data
47            // - Status: 200
48            // - Data: OK
49            // - Headers: []
50            Response::new()
51                // Set the response body to be text
52                .text(text)
53                // Set the `Content-Type` header to be `text/html`
54                // Note: This could also be set with the Response::content method
55                .header(HeaderType::ContentType, "text/html")
56        });
57
58        // Define webpage with form
59        // The form data will be post to /form on submit
60        server.route(Method::GET, "/form", |_req| {
61            let page = r#"<form method="post">
62            <label for="name">Name:</label>
63            <input type="text" id="name" name="name"><br><br>
64            <input type="submit" value="Submit">
65      </form>"#;
66
67            Response::new().text(page).content(Content::HTML)
68        });
69
70        // Define a page with path params
71        server.route(Method::GET, "/greet/{name}", |req| {
72            // As this route would ever run without all the path params being filled
73            // It is safe to unwrap if the name is in the path
74            let data = format!("<h1>Hello, {}</h1>", req.param("name").unwrap());
75
76            Response::new().text(data).content(Content::HTML)
77        });
78
79        // You can now goto http://localhost:8080?name=John and should see "Hello, John"
80        // If you goto http://localhost:8080/form and submit the form you should see "Hello, {NAME}"
81        // Also goto http://localhost:8080/greet/John and you should see "Hello, John"
82
83        // Start the server
84        // This will block the current thread
85        server.start().unwrap();
86    }
examples/application_quote_book.rs (line 76)
34fn main() {
35    set_log_level(Level::Trace);
36    let app = App::new(PathBuf::from("quotes.txt"));
37    app.load();
38
39    let mut server = Server::new(Ipv4Addr::LOCALHOST, 8080).state(app);
40
41    // Route to serve the homepage (page that has add quote form)
42    server.route(Method::GET, "/", |_| {
43        Response::new()
44            .text(String::new() + HEADER + HOME)
45            .content(Content::HTML)
46    });
47
48    // Route to handle creating new quotes.
49    // After successful creation the user will be redirected to the new quotes page.
50    server.stateful_route(Method::POST, "/api/new", |app, req| {
51        let form = Query::from_body(&String::from_utf8_lossy(&req.body));
52        let name =
53            url::decode(form.get("author").expect("No author supplied")).expect("Invalid author");
54        let body =
55            url::decode(form.get("quote").expect("No quote supplied")).expect("Invalid quote");
56
57        let quote = Quote {
58            name,
59            value: body,
60            date: now(),
61        };
62        let mut quotes = app.quotes.write().unwrap();
63        let id = quotes.len();
64        quotes.insert(id.to_string(), quote);
65        drop(quotes);
66        trace!(Level::Trace, "Added new quote #{id}");
67
68        app.save();
69        Response::new()
70            .status(Status::SeeOther)
71            .header(HeaderType::Location, format!("/quote/{id}"))
72            .text("Redirecting to quote page.")
73    });
74
75    server.stateful_route(Method::GET, "/quote/{id}", |app, req| {
76        let id = req.param("id").unwrap();
77        if id == "undefined" {
78            return Response::new();
79        }
80
81        let id = id.parse::<usize>().expect("ID is not a valid integer");
82        let quotes = app.quotes.read().unwrap();
83        if id >= quotes.len() {
84            return Response::new()
85                .status(Status::NotFound)
86                .text(format!("No quote with the id {id} was found."));
87        }
88
89        let quote = quotes.get(&id.to_string()).unwrap();
90        Response::new().content(Content::HTML).text(
91            String::new()
92                + HEADER
93                + &QUOTE
94                    .replace("{QUOTE}", &quote.value)
95                    .replace("{AUTHOR}", &quote.name)
96                    .replace("{TIME}", &imp_date(quote.date)),
97        )
98    });
99
100    server.stateful_route(Method::GET, "/quotes", |app, _req| {
101        let mut out = String::from(HEADER);
102        out.push_str("<ul>");
103        for i in app.quotes.read().unwrap().iter() {
104            out.push_str(&format!(
105                "<li><a href=\"/quote/{}\">\"{}\" - {}</a></li>\n",
106                i.0, i.1.name, i.1.value
107            ));
108        }
109
110        Response::new().text(out + "</ul>").content(Content::HTML)
111    });
112
113    // Note: In a production application you may want to multithread the server with the Server::start_threaded method.
114    server.start().unwrap();
115}
examples/application_paste_bin.rs (line 108)
21fn main() {
22    // Create Server
23    let mut server = Server::new("localhost", 8080).state(RwLock::new(Vec::new()));
24
25    // New paste interface
26    server.route(Method::GET, "/", |_req| {
27        Response::new().content(Content::HTML).text(
28            r#"
29        <form action="/new-form" method="post">
30        <input type="text" name="name" id="name" placeholder="Title">
31        
32        <br />
33        <textarea id="body" name="body" rows="5" cols="33"></textarea>
34        <input type="submit" value="Submit" />
35    </form>
36    "#,
37        )
38    });
39
40    // New paste API handler
41    server.stateful_route(Method::POST, "/new", move |app, req| {
42        // Make sure paste data isn't too long
43        if req.body.len() > DATA_LIMIT {
44            return Response::new()
45                .status(Status::NotFound)
46                .text("Data too big!");
47        }
48
49        // Get the data as string
50        let body_str = String::from_utf8_lossy(&req.body).to_string();
51
52        // Get the name from the Name header
53        let name = req.headers.get("Name").unwrap_or("Untitled");
54
55        let paste = Paste {
56            name: name.to_owned(),
57            body: body_str,
58            time: Instant::now(),
59        };
60
61        // Push this paste to the pastes vector
62        let mut pastes = app.write().unwrap();
63        let id = pastes.len();
64        pastes.push(paste);
65
66        // Send Redirect response
67        Response::new()
68            .status(Status::MovedPermanently)
69            .header(HeaderType::Location, format!("/p/{id}"))
70            .text(format!("Redirecting to /p/{id}."))
71    });
72
73    // New paste form handler
74    server.stateful_route(Method::POST, "/new-form", |app, req| {
75        // Get data from response
76        let query = Query::from_body(String::from_utf8_lossy(&req.body).borrow());
77        let name = url::decode(query.get("name").unwrap_or("Untitled")).expect("Invalid name");
78        let body = url::decode(query.get("body").expect("No body supplied")).expect("Invalid body");
79
80        // Make sure paste data isn't too long
81        if body.len() > DATA_LIMIT {
82            return Response::new()
83                .status(Status::NotFound)
84                .text("Data too big!");
85        }
86
87        let paste = Paste {
88            name,
89            body,
90            time: Instant::now(),
91        };
92
93        // Push this paste to the pastes vector
94        let mut pastes = app.write().unwrap();
95        let id = pastes.len();
96        pastes.push(paste);
97
98        // Send Redirect response
99        Response::new()
100            .status(Status::MovedPermanently)
101            .text("Ok")
102            .header(HeaderType::Location, format!("/p/{}", id))
103    });
104
105    // Get pate handler
106    server.stateful_route(Method::GET, "/p/{id}", move |app, req| {
107        // Get is from path param
108        let id = req.param("id").unwrap().parse::<usize>().unwrap();
109
110        // Get the paste by id
111        let paste = &app.read().unwrap()[id];
112
113        // Send paste
114        Response::new().text(&paste.body)
115    });
116
117    // View all pastes
118    server.stateful_route(Method::GET, "/pastes", move |app, _req| {
119        // Starter HTML
120        let mut out = String::from(
121            r#"<a href="/">New Paste</a><meta charset="UTF-8"><table><tr><th>Name</th><th>Date</th><th>Link</th></tr>"#,
122        );
123
124        // Add a table row for each paste
125        for (i, e) in app.read().unwrap().iter().enumerate() {
126            out.push_str(&format!(
127                "<tr><td>{}</td><td>{}</td><td><a href=\"/p/{}\">๐Ÿ”—</a></td></tr>",
128                e.name,
129                fmt_relative_time(e.time.elapsed().as_secs()),
130                i
131            ));
132        }
133
134        // Send HTML
135        Response::new()
136            .text(format!("{}</table>", out))
137            .content(Content::HTML)
138    });
139
140    server.start().unwrap();
141}
Source

pub fn body_str(&self) -> Cow<'_, str>

Gets the body of the request as a string. This uses the String::from_utf8_lossy method, so it will replace invalid UTF-8 characters with the unicode replacement character (๏ฟฝ). If you want to use a different encoding or handle invalid characters, use a string method on the body field.

Trait Implementationsยง

Sourceยง

impl Debug for Request

Sourceยง

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Sourceยง

impl RealIp for Request

Sourceยง

fn real_ip_header(&self, header: impl Into<HeaderType>) -> IpAddr

Gets the โ€˜real IPโ€™ of a client by parsing the value of header into an IpAddr. If the connection is not coming from localhost, the header isnโ€™t found or the header contains an invalid IP address, the raw socket address will be returned. Read more
Sourceยง

fn real_ip(&self) -> IpAddr

Sourceยง

impl ServerSentEventsExt for Request

Sourceยง

fn sse(&self) -> Result<ServerSentEventStream>

Initiates a SSE connection on the request.
Sourceยง

impl<'a> TryFrom<&'a Request> for MultipartData<'a>

Sourceยง

type Error = MultipartError

The type returned in the event of a conversion error.
Sourceยง

fn try_from(req: &'a Request) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementationsยง

Blanket Implementationsยง

Sourceยง

impl<T> Any for T
where T: 'static + ?Sized,

Sourceยง

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Sourceยง

impl<T> Borrow<T> for T
where T: ?Sized,

Sourceยง

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Sourceยง

impl<T> BorrowMut<T> for T
where T: ?Sized,

Sourceยง

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Sourceยง

impl<T> From<T> for T

Sourceยง

fn from(t: T) -> T

Returns the argument unchanged.

Sourceยง

impl<T, U> Into<U> for T
where U: From<T>,

Sourceยง

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Sourceยง

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Sourceยง

type Error = Infallible

The type returned in the event of a conversion error.
Sourceยง

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Sourceยง

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Sourceยง

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Sourceยง

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.