pub struct Response {
pub status: Status,
pub data: ResponseBody,
pub headers: Headers,
pub reason: Option<String>,
pub flag: ResponseFlag,
}
Expand description
Http Response
Fieldsยง
ยงstatus: Status
Response status code
data: ResponseBody
Response Data.
Can be either a Static Vec<u8>
or a Stream (impl Read
)
headers: Headers
List of response headers. This does not contain the default headers.
reason: Option<String>
Response reason phrase. If this is None, the reason phrase will be automatically generated based on the status code.
flag: ResponseFlag
Response Flags:
- Close: Set the Connection header to close and will close the connection after the response is sent.
- End: End the connection without sending a response
Implementationsยง
Sourceยงimpl Response
impl Response
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new Blank Response
Default data is as follows
- Status: 200
- Data: OK
- Headers: Vec::new()
ยงExample
Response::new();
Examples found in repository?
23fn main() {
24 set_log_level(Level::Debug);
25 let mut server = Server::<()>::new([127, 0, 0, 1], 8080);
26 server.route(Method::ANY, "**", |_req| Response::new());
27
28 Middleware1.attach(&mut server);
29 Middleware2.attach(&mut server);
30 Middleware3.attach(&mut server);
31 Middleware4.attach(&mut server);
32 Middleware5.attach(&mut server);
33
34 server.start().unwrap();
35}
More examples
41 fn exec(&self) {
42 // Set the log level to Trace (shows some helpful information during startup)
43 // The default is Level::Error
44 set_log_level(Level::Trace);
45 trace!(Level::Trace, "Setting log level to Trace");
46 trace!(Level::Error, "Example error message");
47
48 // Create a new Server instance on localhost port 8080
49 let mut server = Server::<()>::new("localhost", 8080);
50
51 server.route(Method::GET, "/", |req| {
52 // The default log level is Level::Trace so this will be logged
53 trace!("Request from {}", req.address.ip());
54 Response::new()
55 });
56
57 server.start().unwrap();
58 }
54 fn exec(&self) {
55 // Create a new Server instance on localhost port 8080
56 let mut server = Server::<()>::new("localhost", 8080);
57
58 // Define a basic route
59 server.route(Method::GET, "/", |_req| {
60 Response::new().text("Hello World!").content(Content::TXT)
61 });
62
63 // Here is where we will attach our Middleware to the Server
64 // This is super easy
65 Log.attach(&mut server);
66
67 // You can now goto http://localhost:8080 you should see that the request is printed to the console
68 // It should look something like this: `[127.0.0.1] GET `
69
70 // Start the server
71 // This will block the current thread
72 server.start().unwrap();
73 }
24 fn exec(&self) {
25 // Create a server on localhost port 8080 with a state of App
26 let mut server = Server::<App>::new("localhost", 8080).state(App::default());
27
28 // Add catch all route that takes in state and the request
29 server.stateful_route(Method::ANY, "**", |sta, _req| {
30 // Respond with and increment request count
31 Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
32 });
33
34 // Start the server
35 // This will block the current thread
36 // Because there is a stateful route, this will panic if no state is set
37 server.start().unwrap();
38
39 // Now go to http://localhost:8080
40 // You should see the request count increment each time you refresh
41 }
24 fn exec(&self) {
25 // Create a new Server instance on localhost port 8080
26 let mut server = Server::<()>::new("localhost", 8080);
27
28 // Define a handler for GET "/"
29 server.route(Method::GET, "/", |_req| {
30 Response::new()
31 // hopefully the ThreadId.as_u64 method will become stable
32 // until then im stuck with this mess for the example
33 // It just gets the thread ID to show the user what thread is handling the request
34 .text(format!(
35 "Hello from thread number {:#?}!",
36 unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
37 - 1
38 ))
39 .content(Content::TXT)
40 });
41
42 // Start the server with 8 threads
43 // This will block the current thread
44 server.start_threaded(8).unwrap();
45
46 // If you go to http://localhost:8080 you should see the thread ID change with each refresh
47 }
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 }
- examples/basic/serve_file.rs
- examples/basic/routing.rs
- examples/basic/rate_limit.rs
- examples/basic/error_handling.rs
- examples/basic/serve_static.rs
- examples/basic/basic.rs
- examples/basic/logging.rs
- examples/basic/cookie.rs
- examples/basic/data.rs
- examples/application_quote_book.rs
- examples/basic/header.rs
- examples/application_paste_bin.rs
Sourcepub fn status(self, code: impl Into<Status>) -> Self
pub fn status(self, code: impl Into<Status>) -> Self
Add a status code to a Response.
This accepts Status
as well as a u16
.
ยงExample
// Create Response
Response::new().status(Status::Ok);
Examples found in repository?
19 fn exec(&self) {
20 // Create a new Server instance on localhost port 8080
21 let mut server = Server::<()>::new("localhost", 8080);
22
23 // Define a handler for GET "/"
24 server.route(Method::GET, "/", |_req| {
25 // Try to open a file
26 match File::open("examples/basic/data/index.html") {
27 // If its found send it as response
28 // Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
29 // This is more efficient than reading the whole file into memory and then sending it
30 Ok(content) => Response::new().stream(content).content(Content::HTML),
31
32 // If the file is not found, send a 404 response
33 Err(_) => Response::new()
34 .status(Status::NotFound)
35 .text("Not Found :/")
36 .content(Content::TXT),
37 }
38 });
39
40 // View the file at http://localhost:8080
41
42 // Start the server
43 // This will block the current thread
44 server.start().unwrap();
45 }
More examples
22 fn exec(&self) {
23 // Create a new Server instance on localhost port 8080
24 let mut server: Server = Server::<()>::new("localhost", 8080);
25
26 // Define 404 page
27 // This route will run for all requests but because any other route
28 // will take priority it will only run when no other route is defined.
29 /* PRIO 0 */
30 server.route(Method::ANY, "**", |_req| {
31 Response::new()
32 .status(Status::NotFound)
33 .text("The page you are looking for does not exist :/")
34 .content(Content::TXT)
35 });
36
37 // Define a route
38 // As this is defined last, it will take a higher priority
39 /* PRIO 1 */
40 server.route(Method::GET, "/", |_req| {
41 Response::new().text("Hello World!").content(Content::TXT)
42 });
43
44 // Now goto http://localhost:8080/ and you should see "Hello World"
45 // But if you go to http://localhost:8080/somthing-else you should see the 404 page
46
47 // Start the server
48 // This will block the current thread
49 server.start().unwrap();
50 }
15 fn exec(&self) {
16 // Create a new Server instance on localhost port 8080
17 let mut server = Server::<()>::new("localhost", 8080);
18
19 // Define a handler for GET "/"
20 server.route(Method::GET, "/", |_req| {
21 Response::new().text("Hello World!").content(Content::TXT)
22 });
23
24 // For this example, we'll limit requests to 1 every 2 seconds
25
26 // Make a new Ratelimater
27 // Default Limit is 10
28 // Default Timeout is 60 sec
29 RateLimiter::new()
30 // Override the Limit to 1
31 .limit(1)
32 // Override the timeout to 2
33 .timeout(2)
34 // Override the Handler
35 .handler(Box::new(|_req| {
36 Some(
37 Response::new()
38 .status(Status::TooManyRequests)
39 .text("AHHHH!!! Too Many Requests")
40 .content(Content::TXT),
41 )
42 }))
43 // Attach to the server
44 .attach(&mut server);
45
46 // Now if you goto http://localhost:8080/ and reload a bunch of times,
47 // you'll see the rate limiter kicking in.
48
49 // Start the server
50 // This will block the current thread
51 server.start().unwrap();
52 }
20 fn exec(&self) {
21 // Create a new Server instance on localhost port 8080
22 let mut server = Server::<()>::new("localhost", 8080);
23
24 // Define a route that will panic
25 server.route(Method::GET, "/panic", |_req| panic!("This is a panic!"));
26
27 // Give the server a main page
28 server.route(Method::GET, "/", |_req| {
29 Response::new()
30 .text(r#"<a href="/panic">PANIC</a>"#)
31 .content(Content::HTML)
32 });
33
34 // You can optionally define a custom error handler
35 // This can be defined anywhere in the server and will take affect for all routes
36 // Its like a normal route, but it will only be called if the route panics
37 let errors = AtomicUsize::new(1);
38 server.error_handler(move |_state, _req, err| {
39 Response::new()
40 .status(Status::InternalServerError)
41 .text(format!(
42 "<h1>Internal Server Error #{}</h1><br>Panicked at '{}'",
43 errors.fetch_add(1, Ordering::Relaxed),
44 err
45 ))
46 .content(Content::HTML)
47 });
48
49 // You can now goto http://localhost:8080/panic
50 // This will cause the route to panic and return a 500 error
51
52 // Start the server
53 // This will block the current thread
54 server.start().unwrap();
55 }
17 fn exec(&self) {
18 // Create a new Server instance on localhost port 8080
19 let mut server = Server::<()>::new("localhost", 8080);
20
21 // Make a new static file server with a path
22 extension::ServeStatic::new(STATIC_DIR)
23 // The middleware priority is by most recently defined.
24 // The middleware function takes 3 parameters: the request, the response, and weather the file was loaded successfully.
25 // In your middleware you can modify the response and the bool.
26 .middleware(|req, res, _suc| {
27 // Print path served
28 println!("Served: {}", req.path);
29 // Return none to not mess with response
30 // Or in this case add a header and pass through the success value
31 res.headers.push(Header::new("X-Static", "true"));
32 })
33 // Function that runs when no file is found to serve
34 // This will run before middleware
35 .not_found(|_req, _dis| {
36 Response::new()
37 .status(Status::NotFound)
38 .text("Page Not Found!")
39 })
40 // Add an extra mime type to the server
41 // It has a lot already
42 .mime_type("key", "value")
43 // Set serve path
44 .path(STATIC_PATH)
45 // Attach the middleware to the server
46 .attach(&mut server);
47
48 // View the file at http://localhost:8080
49 // You should also see a favicon in the browser tab
50
51 // Start the server
52 // This will block the current thread
53 server.start().unwrap();
54 }
17 fn exec(&self) {
18 // Create a new Server instance on localhost port 8080
19 // The type parameter is for a server wide state, which we don't need yet so we use ()
20 // In this example we are setting the ip with a string, but you can also use a Ipv4Addr or [u8; 4]
21 let mut server = Server::<()>::new("localhost", 8080);
22
23 // Define a handler for GET "/"
24 server.route(Method::GET, "/", |_req| {
25 Response::new()
26 // By default the status is 200 (OK)
27 // You can also define it yourself with the status method
28 .status(Status::Ok)
29 // By default the reason phrase is derived from the status
30 // But you can also define it yourself with the reason method
31 .reason("OK!")
32 // Although is is named `text` it takes any type that implements Display
33 // So for example numbers, or a serde_json::Value will work
34 .text("Hi :P")
35 // You can also add headers
36 // The header method will take a HeaderType, String, or &str and the value can be a String or &str
37 // (this is not the proper way to use the Date header, but it works for this example)
38 .header(HeaderType::Date, "today")
39 // Now we will set the content type to text/plain; charset=utf-8
40 // The content method just adds a Content-Type header
41 .content(Content::TXT)
42 });
43
44 // Start the server in single threaded mode
45 // This will block the current thread
46 server.start().unwrap();
47
48 // Now navigate to http://localhost:8080 in your browser
49 // You should see "Hi :P"
50 }
Sourcepub fn reason(self, reason: impl AsRef<str>) -> Self
pub fn reason(self, reason: impl AsRef<str>) -> Self
Manually set the Reason Phrase. If this is not set, it will be inferred from the status code. Non standard status codes will have a reason phrase of โOKโ.
// Create Response
let response = Response::new()
.status(Status::Ok)
.reason("Hello");
Examples found in repository?
17 fn exec(&self) {
18 // Create a new Server instance on localhost port 8080
19 // The type parameter is for a server wide state, which we don't need yet so we use ()
20 // In this example we are setting the ip with a string, but you can also use a Ipv4Addr or [u8; 4]
21 let mut server = Server::<()>::new("localhost", 8080);
22
23 // Define a handler for GET "/"
24 server.route(Method::GET, "/", |_req| {
25 Response::new()
26 // By default the status is 200 (OK)
27 // You can also define it yourself with the status method
28 .status(Status::Ok)
29 // By default the reason phrase is derived from the status
30 // But you can also define it yourself with the reason method
31 .reason("OK!")
32 // Although is is named `text` it takes any type that implements Display
33 // So for example numbers, or a serde_json::Value will work
34 .text("Hi :P")
35 // You can also add headers
36 // The header method will take a HeaderType, String, or &str and the value can be a String or &str
37 // (this is not the proper way to use the Date header, but it works for this example)
38 .header(HeaderType::Date, "today")
39 // Now we will set the content type to text/plain; charset=utf-8
40 // The content method just adds a Content-Type header
41 .content(Content::TXT)
42 });
43
44 // Start the server in single threaded mode
45 // This will block the current thread
46 server.start().unwrap();
47
48 // Now navigate to http://localhost:8080 in your browser
49 // You should see "Hi :P"
50 }
Sourcepub fn text(self, text: impl Display) -> Self
pub fn text(self, text: impl Display) -> Self
Add text as data to a Response.
Will accept any type that implements Display, such as String
, str
, i32
, serde_json::Value, etc.
This response type is considered static and will be sent in one go, not chunked.
ยงExample
// Create Response
let response = Response::new()
.text("Hello from afire!");
Examples found in repository?
54 fn exec(&self) {
55 // Create a new Server instance on localhost port 8080
56 let mut server = Server::<()>::new("localhost", 8080);
57
58 // Define a basic route
59 server.route(Method::GET, "/", |_req| {
60 Response::new().text("Hello World!").content(Content::TXT)
61 });
62
63 // Here is where we will attach our Middleware to the Server
64 // This is super easy
65 Log.attach(&mut server);
66
67 // You can now goto http://localhost:8080 you should see that the request is printed to the console
68 // It should look something like this: `[127.0.0.1] GET `
69
70 // Start the server
71 // This will block the current thread
72 server.start().unwrap();
73 }
More examples
24 fn exec(&self) {
25 // Create a server on localhost port 8080 with a state of App
26 let mut server = Server::<App>::new("localhost", 8080).state(App::default());
27
28 // Add catch all route that takes in state and the request
29 server.stateful_route(Method::ANY, "**", |sta, _req| {
30 // Respond with and increment request count
31 Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
32 });
33
34 // Start the server
35 // This will block the current thread
36 // Because there is a stateful route, this will panic if no state is set
37 server.start().unwrap();
38
39 // Now go to http://localhost:8080
40 // You should see the request count increment each time you refresh
41 }
24 fn exec(&self) {
25 // Create a new Server instance on localhost port 8080
26 let mut server = Server::<()>::new("localhost", 8080);
27
28 // Define a handler for GET "/"
29 server.route(Method::GET, "/", |_req| {
30 Response::new()
31 // hopefully the ThreadId.as_u64 method will become stable
32 // until then im stuck with this mess for the example
33 // It just gets the thread ID to show the user what thread is handling the request
34 .text(format!(
35 "Hello from thread number {:#?}!",
36 unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
37 - 1
38 ))
39 .content(Content::TXT)
40 });
41
42 // Start the server with 8 threads
43 // This will block the current thread
44 server.start_threaded(8).unwrap();
45
46 // If you go to http://localhost:8080 you should see the thread ID change with each refresh
47 }
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 }
19 fn exec(&self) {
20 // Create a new Server instance on localhost port 8080
21 let mut server = Server::<()>::new("localhost", 8080);
22
23 // Define a handler for GET "/"
24 server.route(Method::GET, "/", |_req| {
25 // Try to open a file
26 match File::open("examples/basic/data/index.html") {
27 // If its found send it as response
28 // Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
29 // This is more efficient than reading the whole file into memory and then sending it
30 Ok(content) => Response::new().stream(content).content(Content::HTML),
31
32 // If the file is not found, send a 404 response
33 Err(_) => Response::new()
34 .status(Status::NotFound)
35 .text("Not Found :/")
36 .content(Content::TXT),
37 }
38 });
39
40 // View the file at http://localhost:8080
41
42 // Start the server
43 // This will block the current thread
44 server.start().unwrap();
45 }
22 fn exec(&self) {
23 // Create a new Server instance on localhost port 8080
24 let mut server: Server = Server::<()>::new("localhost", 8080);
25
26 // Define 404 page
27 // This route will run for all requests but because any other route
28 // will take priority it will only run when no other route is defined.
29 /* PRIO 0 */
30 server.route(Method::ANY, "**", |_req| {
31 Response::new()
32 .status(Status::NotFound)
33 .text("The page you are looking for does not exist :/")
34 .content(Content::TXT)
35 });
36
37 // Define a route
38 // As this is defined last, it will take a higher priority
39 /* PRIO 1 */
40 server.route(Method::GET, "/", |_req| {
41 Response::new().text("Hello World!").content(Content::TXT)
42 });
43
44 // Now goto http://localhost:8080/ and you should see "Hello World"
45 // But if you go to http://localhost:8080/somthing-else you should see the 404 page
46
47 // Start the server
48 // This will block the current thread
49 server.start().unwrap();
50 }
Sourcepub fn bytes(self, bytes: &[u8]) -> Self
pub fn bytes(self, bytes: &[u8]) -> Self
Add raw bytes as data to a Response. This response type is considered static and will be sent in one go, not chunked.
ยงExample
// Create Response
let response = Response::new()
.bytes(&[79, 75]); // Bytes for "OK"
Sourcepub fn stream(self, stream: impl Read + Send + 'static) -> Self
pub fn stream(self, stream: impl Read + Send + 'static) -> Self
Add a stream as data to a Response.
This response type is considered dynamic and will be streamed to the client in chunks using Transfer-Encoding: chunked
.
ยงExample
const PATH: &str = "path/to/file.txt";
let mut server = Server::<()>::new("localhost", 8080);
server.route(Method::GET, "/download-stream", |_| {
let stream = File::open(PATH).unwrap();
Response::new().stream(stream)
});
Examples found in repository?
19 fn exec(&self) {
20 // Create a new Server instance on localhost port 8080
21 let mut server = Server::<()>::new("localhost", 8080);
22
23 // Define a handler for GET "/"
24 server.route(Method::GET, "/", |_req| {
25 // Try to open a file
26 match File::open("examples/basic/data/index.html") {
27 // If its found send it as response
28 // Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
29 // This is more efficient than reading the whole file into memory and then sending it
30 Ok(content) => Response::new().stream(content).content(Content::HTML),
31
32 // If the file is not found, send a 404 response
33 Err(_) => Response::new()
34 .status(Status::NotFound)
35 .text("Not Found :/")
36 .content(Content::TXT),
37 }
38 });
39
40 // View the file at http://localhost:8080
41
42 // Start the server
43 // This will block the current thread
44 server.start().unwrap();
45 }
Sourcepub fn header(self, key: impl Into<HeaderType>, value: impl AsRef<str>) -> Self
pub fn header(self, key: impl Into<HeaderType>, value: impl AsRef<str>) -> Self
Add a Header to a Response.
Will accept any type that implements AsRef<str>
, so String
, str
, &str
, etc.
ยงExample
// Create Response
let response = Response::new()
.header("Test-Header", "Test-Value");
Examples found in repository?
17 fn exec(&self) {
18 // Create a new Server instance on localhost port 8080
19 // The type parameter is for a server wide state, which we don't need yet so we use ()
20 // In this example we are setting the ip with a string, but you can also use a Ipv4Addr or [u8; 4]
21 let mut server = Server::<()>::new("localhost", 8080);
22
23 // Define a handler for GET "/"
24 server.route(Method::GET, "/", |_req| {
25 Response::new()
26 // By default the status is 200 (OK)
27 // You can also define it yourself with the status method
28 .status(Status::Ok)
29 // By default the reason phrase is derived from the status
30 // But you can also define it yourself with the reason method
31 .reason("OK!")
32 // Although is is named `text` it takes any type that implements Display
33 // So for example numbers, or a serde_json::Value will work
34 .text("Hi :P")
35 // You can also add headers
36 // The header method will take a HeaderType, String, or &str and the value can be a String or &str
37 // (this is not the proper way to use the Date header, but it works for this example)
38 .header(HeaderType::Date, "today")
39 // Now we will set the content type to text/plain; charset=utf-8
40 // The content method just adds a Content-Type header
41 .content(Content::TXT)
42 });
43
44 // Start the server in single threaded mode
45 // This will block the current thread
46 server.start().unwrap();
47
48 // Now navigate to http://localhost:8080 in your browser
49 // You should see "Hi :P"
50 }
More examples
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 }
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 + "E
94 .replace("{QUOTE}", "e.value)
95 .replace("{AUTHOR}", "e.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}
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}
Sourcepub fn headers(self, headers: &[Header]) -> Self
pub fn headers(self, headers: &[Header]) -> Self
Add a list of Headers to a Response.
Only accepts a slice of Header
s.
ยงExample
// Create Response
let response = Response::new()
.headers(&[
Header::new("Content-Type", "text/html"),
Header::new("Test-Header", "Test-Value")
]);
Examples found in repository?
14 fn exec(&self) {
15 // Create a new Server instance on localhost port 8080
16 let mut server = Server::<()>::new("localhost", 8080)
17 // Define server wide default headers
18 // These will be send with every response
19 // If the same header is defined in the route it will be put before the default header
20 // Although it is not guaranteed to be the one picked by the client it usually is
21 // At the bottom of this file is a representation of the order of the headers
22 .default_header("X-Server-Header", "This is a server wide header")
23 // You can also use the HeaderType enum to define a header type
24 // This is also true with the .header method on the Response struct
25 .default_header(HeaderType::Server, "afire");
26
27 // Define a route to redirect to another website
28 server.route(Method::GET, "/", |_req| {
29 // Because this is all bout headers I have put the header vector here
30 let headers = vec![
31 // Tell the client what type of data we are sending
32 afire::Header::new(HeaderType::ContentType, "text/html"),
33 // Tell the client to redirect to another website
34 afire::Header::new(HeaderType::Location, "https://connorcode.com"),
35 // Custom header
36 afire::Header::new("X-Custom-Header", "This is a custom header"),
37 ];
38
39 // Define response body
40 // In this case this should only be seen if the client doesn't support redirects for some reason
41 let text = "<a href=\"https://connorcode.com\">connorcode</a>";
42
43 // The response code of 308 tells the client to redirect to the location specified in the header
44 // There are other response codes you can use too
45 // 301 -> Moved Permanently
46 // 302 -> Found
47 // 303 -> See Other
48 // 307 -> Temporary Redirect
49 // 308 -> Permanent Redirect
50 Response::new()
51 .status(Status::PermanentRedirect)
52 .text(text)
53 .headers(&headers)
54 });
55
56 // Now to define a route to handle client headers
57 // This will just echo the headers back to the client
58 server.route(Method::GET, "/headers", |req| {
59 // Get the headers from the request and make a html string
60 let body = req
61 .headers
62 .iter()
63 .fold(String::new(), |old, new| old + &format!("{:?}<br />", new));
64
65 // Create a response with the headers
66 Response::new().text(body).content(Content::HTML)
67 });
68
69 // You can now goto http://localhost:8080 you should see a redirect to https://connorcode.com
70 // And you can goto http://localhost:8080/headers to see the headers your client sent to the server
71
72 // Start the server
73 // This will block the current thread
74 server.start().unwrap();
75 }
Sourcepub fn close(self) -> Self
pub fn close(self) -> Self
Will set the Connection: close
header on the Response.
Then it will close the connection after the Response has been sent.
ยงExample
// Create Response
let response = Response::new()
.text("goodbye!")
.close();
Add a cookie to a response.
The SetCookie
will be converted to a Header
and added to the Response.
ยงExample
// Create Response and add cookie
let response = Response::new()
.cookie(SetCookie::new("name", "value"))
.cookie(SetCookie::new("name2", "value2"));
Examples found in repository?
17 fn exec(&self) {
18 // Create a new Server instance on localhost port 8080
19 let mut server = Server::<()>::new([127, 0, 0, 1], 8080);
20
21 // Define a route to show request cookies as a table
22 server.route(Method::GET, "/", |req| {
23 // Return all cookies in a *messy* html table
24 let mut html = String::new();
25 html.push_str("<style>table, th, td {border:1px solid black;}</style>");
26 html.push_str("<table>");
27 html.push_str("<tr><th>Name</th><th>Value</th></tr>");
28 for cookie in &*req.cookies {
29 html.push_str("<tr><td>");
30 html.push_str(&cookie.name);
31 html.push_str("</td><td>");
32 html.push_str(&cookie.value);
33 html.push_str("</td></tr>");
34 }
35 html.push_str("</table>");
36
37 Response::new().text(html).content(Content::HTML)
38 });
39
40 // Set a cookie defined in the Query
41 server.route(Method::GET, "/set", |req| {
42 // Create a new cookie
43 let cookie = SetCookie::new(
44 req.query.get("name").unwrap_or("test"),
45 req.query.get("value").unwrap_or("test"),
46 )
47 // Set some options
48 .max_age(60 * 60)
49 .path("/");
50
51 let body = format!(
52 "Set Cookie '{}' to '{}'",
53 cookie.cookie.name, cookie.cookie.value
54 );
55
56 // Set the cookie
57 Response::new()
58 .text(body)
59 .content(Content::HTML)
60 .cookie(cookie)
61 });
62
63 // Now goto http://localhost:8080/set?name=hello&value=world
64 // Then goto http://localhost:8080/ and you should see a table with the cookie
65
66 // Start the server in single threaded mode
67 // This will block the current thread
68 server.start().unwrap();
69 }
Add a list of cookies to a response.
ยงExample
// Create Response and add cookie
let response = Response::new()
.cookies(&[
SetCookie::new("name", "value"),
SetCookie::new("name2", "value2")
]);
Sourcepub fn content(self, content_type: Content<'_>) -> Self
pub fn content(self, content_type: Content<'_>) -> Self
Set a Content Type on a Response with a Content
enum.
This will add a Content-Type
header to the Response.
ยงExample
// Create Response and type
let response = Response::new()
.content(Content::HTML);
Examples found in repository?
54 fn exec(&self) {
55 // Create a new Server instance on localhost port 8080
56 let mut server = Server::<()>::new("localhost", 8080);
57
58 // Define a basic route
59 server.route(Method::GET, "/", |_req| {
60 Response::new().text("Hello World!").content(Content::TXT)
61 });
62
63 // Here is where we will attach our Middleware to the Server
64 // This is super easy
65 Log.attach(&mut server);
66
67 // You can now goto http://localhost:8080 you should see that the request is printed to the console
68 // It should look something like this: `[127.0.0.1] GET `
69
70 // Start the server
71 // This will block the current thread
72 server.start().unwrap();
73 }
More examples
24 fn exec(&self) {
25 // Create a new Server instance on localhost port 8080
26 let mut server = Server::<()>::new("localhost", 8080);
27
28 // Define a handler for GET "/"
29 server.route(Method::GET, "/", |_req| {
30 Response::new()
31 // hopefully the ThreadId.as_u64 method will become stable
32 // until then im stuck with this mess for the example
33 // It just gets the thread ID to show the user what thread is handling the request
34 .text(format!(
35 "Hello from thread number {:#?}!",
36 unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
37 - 1
38 ))
39 .content(Content::TXT)
40 });
41
42 // Start the server with 8 threads
43 // This will block the current thread
44 server.start_threaded(8).unwrap();
45
46 // If you go to http://localhost:8080 you should see the thread ID change with each refresh
47 }
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 }
19 fn exec(&self) {
20 // Create a new Server instance on localhost port 8080
21 let mut server = Server::<()>::new("localhost", 8080);
22
23 // Define a handler for GET "/"
24 server.route(Method::GET, "/", |_req| {
25 // Try to open a file
26 match File::open("examples/basic/data/index.html") {
27 // If its found send it as response
28 // Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
29 // This is more efficient than reading the whole file into memory and then sending it
30 Ok(content) => Response::new().stream(content).content(Content::HTML),
31
32 // If the file is not found, send a 404 response
33 Err(_) => Response::new()
34 .status(Status::NotFound)
35 .text("Not Found :/")
36 .content(Content::TXT),
37 }
38 });
39
40 // View the file at http://localhost:8080
41
42 // Start the server
43 // This will block the current thread
44 server.start().unwrap();
45 }
22 fn exec(&self) {
23 // Create a new Server instance on localhost port 8080
24 let mut server: Server = Server::<()>::new("localhost", 8080);
25
26 // Define 404 page
27 // This route will run for all requests but because any other route
28 // will take priority it will only run when no other route is defined.
29 /* PRIO 0 */
30 server.route(Method::ANY, "**", |_req| {
31 Response::new()
32 .status(Status::NotFound)
33 .text("The page you are looking for does not exist :/")
34 .content(Content::TXT)
35 });
36
37 // Define a route
38 // As this is defined last, it will take a higher priority
39 /* PRIO 1 */
40 server.route(Method::GET, "/", |_req| {
41 Response::new().text("Hello World!").content(Content::TXT)
42 });
43
44 // Now goto http://localhost:8080/ and you should see "Hello World"
45 // But if you go to http://localhost:8080/somthing-else you should see the 404 page
46
47 // Start the server
48 // This will block the current thread
49 server.start().unwrap();
50 }
15 fn exec(&self) {
16 // Create a new Server instance on localhost port 8080
17 let mut server = Server::<()>::new("localhost", 8080);
18
19 // Define a handler for GET "/"
20 server.route(Method::GET, "/", |_req| {
21 Response::new().text("Hello World!").content(Content::TXT)
22 });
23
24 // For this example, we'll limit requests to 1 every 2 seconds
25
26 // Make a new Ratelimater
27 // Default Limit is 10
28 // Default Timeout is 60 sec
29 RateLimiter::new()
30 // Override the Limit to 1
31 .limit(1)
32 // Override the timeout to 2
33 .timeout(2)
34 // Override the Handler
35 .handler(Box::new(|_req| {
36 Some(
37 Response::new()
38 .status(Status::TooManyRequests)
39 .text("AHHHH!!! Too Many Requests")
40 .content(Content::TXT),
41 )
42 }))
43 // Attach to the server
44 .attach(&mut server);
45
46 // Now if you goto http://localhost:8080/ and reload a bunch of times,
47 // you'll see the rate limiter kicking in.
48
49 // Start the server
50 // This will block the current thread
51 server.start().unwrap();
52 }