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?
23 24 25 26 27 28 29 30 31 32 33 34 35
fn main() {
set_log_level(Level::Debug);
let mut server = Server::<()>::new([127, 0, 0, 1], 8080);
server.route(Method::ANY, "**", |_req| Response::new());
Middleware1.attach(&mut server);
Middleware2.attach(&mut server);
Middleware3.attach(&mut server);
Middleware4.attach(&mut server);
Middleware5.attach(&mut server);
server.start().unwrap();
}
More examples
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
fn exec(&self) {
// Set the log level to Trace (shows some helpful information during startup)
// The default is Level::Error
set_log_level(Level::Trace);
trace!(Level::Trace, "Setting log level to Trace");
trace!(Level::Error, "Example error message");
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
server.route(Method::GET, "/", |req| {
// The default log level is Level::Trace so this will be logged
trace!("Request from {}", req.address.ip());
Response::new()
});
server.start().unwrap();
}
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a basic route
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// Here is where we will attach our Middleware to the Server
// This is super easy
Log.attach(&mut server);
// You can now goto http://localhost:8080 you should see that the request is printed to the console
// It should look something like this: `[127.0.0.1] GET `
// Start the server
// This will block the current thread
server.start().unwrap();
}
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
fn exec(&self) {
// Create a server on localhost port 8080 with a state of App
let mut server = Server::<App>::new("localhost", 8080).state(App::default());
// Add catch all route that takes in state and the request
server.stateful_route(Method::ANY, "**", |sta, _req| {
// Respond with and increment request count
Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
});
// Start the server
// This will block the current thread
// Because there is a stateful route, this will panic if no state is set
server.start().unwrap();
// Now go to http://localhost:8080
// You should see the request count increment each time you refresh
}
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new()
// hopefully the ThreadId.as_u64 method will become stable
// until then im stuck with this mess for the example
// It just gets the thread ID to show the user what thread is handling the request
.text(format!(
"Hello from thread number {:#?}!",
unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
- 1
))
.content(Content::TXT)
});
// Start the server with 8 threads
// This will block the current thread
server.start_threaded(8).unwrap();
// If you go to http://localhost:8080 you should see the thread ID change with each refresh
}
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server: Server = Server::<()>::new("localhost", 8081);
// Define a handler for GET "/greet/{name}"
// This will handel requests with anything where the {name} is
// This includes "/greet/bob", "/greet/fin"
server.route(Method::GET, "/greet/{name}", |req| {
// Get name path param
let name = req.param("name").unwrap();
// Make a nice Message to send
let message = format!("Hello, {}", name);
// Send Response
Response::new().text(message).content(Content::TXT)
});
// Define a greet route for Darren because he is very cool
// This will take priority over the other route as it is defined after
server.route(Method::GET, "/greet/Darren/", |_req| {
Response::new().text("Hello, Darren. You are very cool")
});
// Start the server
// This will block the current thread
server.start().unwrap();
}
- 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 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
// Try to open a file
match File::open("examples/basic/data/index.html") {
// If its found send it as response
// Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
// This is more efficient than reading the whole file into memory and then sending it
Ok(content) => Response::new().stream(content).content(Content::HTML),
// If the file is not found, send a 404 response
Err(_) => Response::new()
.status(Status::NotFound)
.text("Not Found :/")
.content(Content::TXT),
}
});
// View the file at http://localhost:8080
// Start the server
// This will block the current thread
server.start().unwrap();
}
More examples
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server: Server = Server::<()>::new("localhost", 8080);
// Define 404 page
// This route will run for all requests but because any other route
// will take priority it will only run when no other route is defined.
/* PRIO 0 */
server.route(Method::ANY, "**", |_req| {
Response::new()
.status(Status::NotFound)
.text("The page you are looking for does not exist :/")
.content(Content::TXT)
});
// Define a route
// As this is defined last, it will take a higher priority
/* PRIO 1 */
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// Now goto http://localhost:8080/ and you should see "Hello World"
// But if you go to http://localhost:8080/somthing-else you should see the 404 page
// Start the server
// This will block the current thread
server.start().unwrap();
}
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// For this example, we'll limit requests to 1 every 2 seconds
// Make a new Ratelimater
// Default Limit is 10
// Default Timeout is 60 sec
RateLimiter::new()
// Override the Limit to 1
.limit(1)
// Override the timeout to 2
.timeout(2)
// Override the Handler
.handler(Box::new(|_req| {
Some(
Response::new()
.status(Status::TooManyRequests)
.text("AHHHH!!! Too Many Requests")
.content(Content::TXT),
)
}))
// Attach to the server
.attach(&mut server);
// Now if you goto http://localhost:8080/ and reload a bunch of times,
// you'll see the rate limiter kicking in.
// Start the server
// This will block the current thread
server.start().unwrap();
}
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a route that will panic
server.route(Method::GET, "/panic", |_req| panic!("This is a panic!"));
// Give the server a main page
server.route(Method::GET, "/", |_req| {
Response::new()
.text(r#"<a href="/panic">PANIC</a>"#)
.content(Content::HTML)
});
// You can optionally define a custom error handler
// This can be defined anywhere in the server and will take affect for all routes
// Its like a normal route, but it will only be called if the route panics
let errors = AtomicUsize::new(1);
server.error_handler(move |_state, _req, err| {
Response::new()
.status(Status::InternalServerError)
.text(format!(
"<h1>Internal Server Error #{}</h1><br>Panicked at '{}'",
errors.fetch_add(1, Ordering::Relaxed),
err
))
.content(Content::HTML)
});
// You can now goto http://localhost:8080/panic
// This will cause the route to panic and return a 500 error
// Start the server
// This will block the current thread
server.start().unwrap();
}
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Make a new static file server with a path
extension::ServeStatic::new(STATIC_DIR)
// The middleware priority is by most recently defined.
// The middleware function takes 3 parameters: the request, the response, and weather the file was loaded successfully.
// In your middleware you can modify the response and the bool.
.middleware(|req, res, _suc| {
// Print path served
println!("Served: {}", req.path);
// Return none to not mess with response
// Or in this case add a header and pass through the success value
res.headers.push(Header::new("X-Static", "true"));
})
// Function that runs when no file is found to serve
// This will run before middleware
.not_found(|_req, _dis| {
Response::new()
.status(Status::NotFound)
.text("Page Not Found!")
})
// Add an extra mime type to the server
// It has a lot already
.mime_type("key", "value")
// Set serve path
.path(STATIC_PATH)
// Attach the middleware to the server
.attach(&mut server);
// View the file at http://localhost:8080
// You should also see a favicon in the browser tab
// Start the server
// This will block the current thread
server.start().unwrap();
}
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
fn exec(&self) {
// Create a new Server instance on localhost port 8080
// The type parameter is for a server wide state, which we don't need yet so we use ()
// In this example we are setting the ip with a string, but you can also use a Ipv4Addr or [u8; 4]
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new()
// By default the status is 200 (OK)
// You can also define it yourself with the status method
.status(Status::Ok)
// By default the reason phrase is derived from the status
// But you can also define it yourself with the reason method
.reason("OK!")
// Although is is named `text` it takes any type that implements Display
// So for example numbers, or a serde_json::Value will work
.text("Hi :P")
// You can also add headers
// The header method will take a HeaderType, String, or &str and the value can be a String or &str
// (this is not the proper way to use the Date header, but it works for this example)
.header(HeaderType::Date, "today")
// Now we will set the content type to text/plain; charset=utf-8
// The content method just adds a Content-Type header
.content(Content::TXT)
});
// Start the server in single threaded mode
// This will block the current thread
server.start().unwrap();
// Now navigate to http://localhost:8080 in your browser
// You should see "Hi :P"
}
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 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
fn exec(&self) {
// Create a new Server instance on localhost port 8080
// The type parameter is for a server wide state, which we don't need yet so we use ()
// In this example we are setting the ip with a string, but you can also use a Ipv4Addr or [u8; 4]
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new()
// By default the status is 200 (OK)
// You can also define it yourself with the status method
.status(Status::Ok)
// By default the reason phrase is derived from the status
// But you can also define it yourself with the reason method
.reason("OK!")
// Although is is named `text` it takes any type that implements Display
// So for example numbers, or a serde_json::Value will work
.text("Hi :P")
// You can also add headers
// The header method will take a HeaderType, String, or &str and the value can be a String or &str
// (this is not the proper way to use the Date header, but it works for this example)
.header(HeaderType::Date, "today")
// Now we will set the content type to text/plain; charset=utf-8
// The content method just adds a Content-Type header
.content(Content::TXT)
});
// Start the server in single threaded mode
// This will block the current thread
server.start().unwrap();
// Now navigate to http://localhost:8080 in your browser
// You should see "Hi :P"
}
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a basic route
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// Here is where we will attach our Middleware to the Server
// This is super easy
Log.attach(&mut server);
// You can now goto http://localhost:8080 you should see that the request is printed to the console
// It should look something like this: `[127.0.0.1] GET `
// Start the server
// This will block the current thread
server.start().unwrap();
}
More examples
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
fn exec(&self) {
// Create a server on localhost port 8080 with a state of App
let mut server = Server::<App>::new("localhost", 8080).state(App::default());
// Add catch all route that takes in state and the request
server.stateful_route(Method::ANY, "**", |sta, _req| {
// Respond with and increment request count
Response::new().text(sta.count.fetch_add(1, Ordering::Relaxed))
});
// Start the server
// This will block the current thread
// Because there is a stateful route, this will panic if no state is set
server.start().unwrap();
// Now go to http://localhost:8080
// You should see the request count increment each time you refresh
}
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new()
// hopefully the ThreadId.as_u64 method will become stable
// until then im stuck with this mess for the example
// It just gets the thread ID to show the user what thread is handling the request
.text(format!(
"Hello from thread number {:#?}!",
unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
- 1
))
.content(Content::TXT)
});
// Start the server with 8 threads
// This will block the current thread
server.start_threaded(8).unwrap();
// If you go to http://localhost:8080 you should see the thread ID change with each refresh
}
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server: Server = Server::<()>::new("localhost", 8081);
// Define a handler for GET "/greet/{name}"
// This will handel requests with anything where the {name} is
// This includes "/greet/bob", "/greet/fin"
server.route(Method::GET, "/greet/{name}", |req| {
// Get name path param
let name = req.param("name").unwrap();
// Make a nice Message to send
let message = format!("Hello, {}", name);
// Send Response
Response::new().text(message).content(Content::TXT)
});
// Define a greet route for Darren because he is very cool
// This will take priority over the other route as it is defined after
server.route(Method::GET, "/greet/Darren/", |_req| {
Response::new().text("Hello, Darren. You are very cool")
});
// Start the server
// This will block the current thread
server.start().unwrap();
}
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
// Try to open a file
match File::open("examples/basic/data/index.html") {
// If its found send it as response
// Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
// This is more efficient than reading the whole file into memory and then sending it
Ok(content) => Response::new().stream(content).content(Content::HTML),
// If the file is not found, send a 404 response
Err(_) => Response::new()
.status(Status::NotFound)
.text("Not Found :/")
.content(Content::TXT),
}
});
// View the file at http://localhost:8080
// Start the server
// This will block the current thread
server.start().unwrap();
}
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server: Server = Server::<()>::new("localhost", 8080);
// Define 404 page
// This route will run for all requests but because any other route
// will take priority it will only run when no other route is defined.
/* PRIO 0 */
server.route(Method::ANY, "**", |_req| {
Response::new()
.status(Status::NotFound)
.text("The page you are looking for does not exist :/")
.content(Content::TXT)
});
// Define a route
// As this is defined last, it will take a higher priority
/* PRIO 1 */
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// Now goto http://localhost:8080/ and you should see "Hello World"
// But if you go to http://localhost:8080/somthing-else you should see the 404 page
// Start the server
// This will block the current thread
server.start().unwrap();
}
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 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
// Try to open a file
match File::open("examples/basic/data/index.html") {
// If its found send it as response
// Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
// This is more efficient than reading the whole file into memory and then sending it
Ok(content) => Response::new().stream(content).content(Content::HTML),
// If the file is not found, send a 404 response
Err(_) => Response::new()
.status(Status::NotFound)
.text("Not Found :/")
.content(Content::TXT),
}
});
// View the file at http://localhost:8080
// Start the server
// This will block the current thread
server.start().unwrap();
}
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 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
fn exec(&self) {
// Create a new Server instance on localhost port 8080
// The type parameter is for a server wide state, which we don't need yet so we use ()
// In this example we are setting the ip with a string, but you can also use a Ipv4Addr or [u8; 4]
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new()
// By default the status is 200 (OK)
// You can also define it yourself with the status method
.status(Status::Ok)
// By default the reason phrase is derived from the status
// But you can also define it yourself with the reason method
.reason("OK!")
// Although is is named `text` it takes any type that implements Display
// So for example numbers, or a serde_json::Value will work
.text("Hi :P")
// You can also add headers
// The header method will take a HeaderType, String, or &str and the value can be a String or &str
// (this is not the proper way to use the Date header, but it works for this example)
.header(HeaderType::Date, "today")
// Now we will set the content type to text/plain; charset=utf-8
// The content method just adds a Content-Type header
.content(Content::TXT)
});
// Start the server in single threaded mode
// This will block the current thread
server.start().unwrap();
// Now navigate to http://localhost:8080 in your browser
// You should see "Hi :P"
}
More examples
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new(Ipv4Addr::LOCALHOST, 8080);
// Define a route to handel query string
// This will try to find a name value pair in the query string
server.route(Method::GET, "/", |req| {
// Format the response text
let text = format!(
"<h1>Hello, {}!</h1>",
// Get the query value of name and default to "Nobody" if not found
req.query.get("name").unwrap_or("Nobody")
);
Response::new().text(text).content(Content::HTML)
});
// Define another route
// This time to handle form data
server.route(Method::POST, "/form", |req| {
// The body of requests is not part of the req.query
// Instead it is part of the req.body but as a string
// We will need to parse it get it as a query
let body_data = Query::from_body(&String::from_utf8_lossy(&req.body));
let name = body_data.get("name").unwrap_or("Nobody");
let text = format!("<h1>Hello, {}</h1>", name);
// Create a new response, with the following default data
// - Status: 200
// - Data: OK
// - Headers: []
Response::new()
// Set the response body to be text
.text(text)
// Set the `Content-Type` header to be `text/html`
// Note: This could also be set with the Response::content method
.header(HeaderType::ContentType, "text/html")
});
// Define webpage with form
// The form data will be post to /form on submit
server.route(Method::GET, "/form", |_req| {
let page = r#"<form method="post">
<label for="name">Name:</label>
<input type="text" id="name" name="name"><br><br>
<input type="submit" value="Submit">
</form>"#;
Response::new().text(page).content(Content::HTML)
});
// Define a page with path params
server.route(Method::GET, "/greet/{name}", |req| {
// As this route would ever run without all the path params being filled
// It is safe to unwrap if the name is in the path
let data = format!("<h1>Hello, {}</h1>", req.param("name").unwrap());
Response::new().text(data).content(Content::HTML)
});
// You can now goto http://localhost:8080?name=John and should see "Hello, John"
// If you goto http://localhost:8080/form and submit the form you should see "Hello, {NAME}"
// Also goto http://localhost:8080/greet/John and you should see "Hello, John"
// Start the server
// This will block the current thread
server.start().unwrap();
}
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
fn main() {
set_log_level(Level::Trace);
let app = App::new(PathBuf::from("quotes.txt"));
app.load();
let mut server = Server::new(Ipv4Addr::LOCALHOST, 8080).state(app);
// Route to serve the homepage (page that has add quote form)
server.route(Method::GET, "/", |_| {
Response::new()
.text(String::new() + HEADER + HOME)
.content(Content::HTML)
});
// Route to handle creating new quotes.
// After successful creation the user will be redirected to the new quotes page.
server.stateful_route(Method::POST, "/api/new", |app, req| {
let form = Query::from_body(&String::from_utf8_lossy(&req.body));
let name =
url::decode(form.get("author").expect("No author supplied")).expect("Invalid author");
let body =
url::decode(form.get("quote").expect("No quote supplied")).expect("Invalid quote");
let quote = Quote {
name,
value: body,
date: now(),
};
let mut quotes = app.quotes.write().unwrap();
let id = quotes.len();
quotes.insert(id.to_string(), quote);
drop(quotes);
trace!(Level::Trace, "Added new quote #{id}");
app.save();
Response::new()
.status(Status::SeeOther)
.header(HeaderType::Location, format!("/quote/{id}"))
.text("Redirecting to quote page.")
});
server.stateful_route(Method::GET, "/quote/{id}", |app, req| {
let id = req.param("id").unwrap();
if id == "undefined" {
return Response::new();
}
let id = id.parse::<usize>().expect("ID is not a valid integer");
let quotes = app.quotes.read().unwrap();
if id >= quotes.len() {
return Response::new()
.status(Status::NotFound)
.text(format!("No quote with the id {id} was found."));
}
let quote = quotes.get(&id.to_string()).unwrap();
Response::new().content(Content::HTML).text(
String::new()
+ HEADER
+ "E
.replace("{QUOTE}", "e.value)
.replace("{AUTHOR}", "e.name)
.replace("{TIME}", &imp_date(quote.date)),
)
});
server.stateful_route(Method::GET, "/quotes", |app, _req| {
let mut out = String::from(HEADER);
out.push_str("<ul>");
for i in app.quotes.read().unwrap().iter() {
out.push_str(&format!(
"<li><a href=\"/quote/{}\">\"{}\" - {}</a></li>\n",
i.0, i.1.name, i.1.value
));
}
Response::new().text(out + "</ul>").content(Content::HTML)
});
// Note: In a production application you may want to multithread the server with the Server::start_threaded method.
server.start().unwrap();
}
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
fn main() {
// Create Server
let mut server = Server::new("localhost", 8080).state(RwLock::new(Vec::new()));
// New paste interface
server.route(Method::GET, "/", |_req| {
Response::new().content(Content::HTML).text(
r#"
<form action="/new-form" method="post">
<input type="text" name="name" id="name" placeholder="Title">
<br />
<textarea id="body" name="body" rows="5" cols="33"></textarea>
<input type="submit" value="Submit" />
</form>
"#,
)
});
// New paste API handler
server.stateful_route(Method::POST, "/new", move |app, req| {
// Make sure paste data isn't too long
if req.body.len() > DATA_LIMIT {
return Response::new()
.status(Status::NotFound)
.text("Data too big!");
}
// Get the data as string
let body_str = String::from_utf8_lossy(&req.body).to_string();
// Get the name from the Name header
let name = req.headers.get("Name").unwrap_or("Untitled");
let paste = Paste {
name: name.to_owned(),
body: body_str,
time: Instant::now(),
};
// Push this paste to the pastes vector
let mut pastes = app.write().unwrap();
let id = pastes.len();
pastes.push(paste);
// Send Redirect response
Response::new()
.status(Status::MovedPermanently)
.header(HeaderType::Location, format!("/p/{id}"))
.text(format!("Redirecting to /p/{id}."))
});
// New paste form handler
server.stateful_route(Method::POST, "/new-form", |app, req| {
// Get data from response
let query = Query::from_body(String::from_utf8_lossy(&req.body).borrow());
let name = url::decode(query.get("name").unwrap_or("Untitled")).expect("Invalid name");
let body = url::decode(query.get("body").expect("No body supplied")).expect("Invalid body");
// Make sure paste data isn't too long
if body.len() > DATA_LIMIT {
return Response::new()
.status(Status::NotFound)
.text("Data too big!");
}
let paste = Paste {
name,
body,
time: Instant::now(),
};
// Push this paste to the pastes vector
let mut pastes = app.write().unwrap();
let id = pastes.len();
pastes.push(paste);
// Send Redirect response
Response::new()
.status(Status::MovedPermanently)
.text("Ok")
.header(HeaderType::Location, format!("/p/{}", id))
});
// Get pate handler
server.stateful_route(Method::GET, "/p/{id}", move |app, req| {
// Get is from path param
let id = req.param("id").unwrap().parse::<usize>().unwrap();
// Get the paste by id
let paste = &app.read().unwrap()[id];
// Send paste
Response::new().text(&paste.body)
});
// View all pastes
server.stateful_route(Method::GET, "/pastes", move |app, _req| {
// Starter HTML
let mut out = String::from(
r#"<a href="/">New Paste</a><meta charset="UTF-8"><table><tr><th>Name</th><th>Date</th><th>Link</th></tr>"#,
);
// Add a table row for each paste
for (i, e) in app.read().unwrap().iter().enumerate() {
out.push_str(&format!(
"<tr><td>{}</td><td>{}</td><td><a href=\"/p/{}\">๐</a></td></tr>",
e.name,
fmt_relative_time(e.time.elapsed().as_secs()),
i
));
}
// Send HTML
Response::new()
.text(format!("{}</table>", out))
.content(Content::HTML)
});
server.start().unwrap();
}
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 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080)
// Define server wide default headers
// These will be send with every response
// If the same header is defined in the route it will be put before the default header
// Although it is not guaranteed to be the one picked by the client it usually is
// At the bottom of this file is a representation of the order of the headers
.default_header("X-Server-Header", "This is a server wide header")
// You can also use the HeaderType enum to define a header type
// This is also true with the .header method on the Response struct
.default_header(HeaderType::Server, "afire");
// Define a route to redirect to another website
server.route(Method::GET, "/", |_req| {
// Because this is all bout headers I have put the header vector here
let headers = vec![
// Tell the client what type of data we are sending
afire::Header::new(HeaderType::ContentType, "text/html"),
// Tell the client to redirect to another website
afire::Header::new(HeaderType::Location, "https://connorcode.com"),
// Custom header
afire::Header::new("X-Custom-Header", "This is a custom header"),
];
// Define response body
// In this case this should only be seen if the client doesn't support redirects for some reason
let text = "<a href=\"https://connorcode.com\">connorcode</a>";
// The response code of 308 tells the client to redirect to the location specified in the header
// There are other response codes you can use too
// 301 -> Moved Permanently
// 302 -> Found
// 303 -> See Other
// 307 -> Temporary Redirect
// 308 -> Permanent Redirect
Response::new()
.status(Status::PermanentRedirect)
.text(text)
.headers(&headers)
});
// Now to define a route to handle client headers
// This will just echo the headers back to the client
server.route(Method::GET, "/headers", |req| {
// Get the headers from the request and make a html string
let body = req
.headers
.iter()
.fold(String::new(), |old, new| old + &format!("{:?}<br />", new));
// Create a response with the headers
Response::new().text(body).content(Content::HTML)
});
// You can now goto http://localhost:8080 you should see a redirect to https://connorcode.com
// And you can goto http://localhost:8080/headers to see the headers your client sent to the server
// Start the server
// This will block the current thread
server.start().unwrap();
}
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 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new([127, 0, 0, 1], 8080);
// Define a route to show request cookies as a table
server.route(Method::GET, "/", |req| {
// Return all cookies in a *messy* html table
let mut html = String::new();
html.push_str("<style>table, th, td {border:1px solid black;}</style>");
html.push_str("<table>");
html.push_str("<tr><th>Name</th><th>Value</th></tr>");
for cookie in &*req.cookies {
html.push_str("<tr><td>");
html.push_str(&cookie.name);
html.push_str("</td><td>");
html.push_str(&cookie.value);
html.push_str("</td></tr>");
}
html.push_str("</table>");
Response::new().text(html).content(Content::HTML)
});
// Set a cookie defined in the Query
server.route(Method::GET, "/set", |req| {
// Create a new cookie
let cookie = SetCookie::new(
req.query.get("name").unwrap_or("test"),
req.query.get("value").unwrap_or("test"),
)
// Set some options
.max_age(60 * 60)
.path("/");
let body = format!(
"Set Cookie '{}' to '{}'",
cookie.cookie.name, cookie.cookie.value
);
// Set the cookie
Response::new()
.text(body)
.content(Content::HTML)
.cookie(cookie)
});
// Now goto http://localhost:8080/set?name=hello&value=world
// Then goto http://localhost:8080/ and you should see a table with the cookie
// Start the server in single threaded mode
// This will block the current thread
server.start().unwrap();
}
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a basic route
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// Here is where we will attach our Middleware to the Server
// This is super easy
Log.attach(&mut server);
// You can now goto http://localhost:8080 you should see that the request is printed to the console
// It should look something like this: `[127.0.0.1] GET `
// Start the server
// This will block the current thread
server.start().unwrap();
}
More examples
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new()
// hopefully the ThreadId.as_u64 method will become stable
// until then im stuck with this mess for the example
// It just gets the thread ID to show the user what thread is handling the request
.text(format!(
"Hello from thread number {:#?}!",
unsafe { std::mem::transmute::<_, NonZeroU64>(thread::current().id()) }.get()
- 1
))
.content(Content::TXT)
});
// Start the server with 8 threads
// This will block the current thread
server.start_threaded(8).unwrap();
// If you go to http://localhost:8080 you should see the thread ID change with each refresh
}
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server: Server = Server::<()>::new("localhost", 8081);
// Define a handler for GET "/greet/{name}"
// This will handel requests with anything where the {name} is
// This includes "/greet/bob", "/greet/fin"
server.route(Method::GET, "/greet/{name}", |req| {
// Get name path param
let name = req.param("name").unwrap();
// Make a nice Message to send
let message = format!("Hello, {}", name);
// Send Response
Response::new().text(message).content(Content::TXT)
});
// Define a greet route for Darren because he is very cool
// This will take priority over the other route as it is defined after
server.route(Method::GET, "/greet/Darren/", |_req| {
Response::new().text("Hello, Darren. You are very cool")
});
// Start the server
// This will block the current thread
server.start().unwrap();
}
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
// Try to open a file
match File::open("examples/basic/data/index.html") {
// If its found send it as response
// Because we used File::open and not fs::read, we can use the stream method to send the file in chunks
// This is more efficient than reading the whole file into memory and then sending it
Ok(content) => Response::new().stream(content).content(Content::HTML),
// If the file is not found, send a 404 response
Err(_) => Response::new()
.status(Status::NotFound)
.text("Not Found :/")
.content(Content::TXT),
}
});
// View the file at http://localhost:8080
// Start the server
// This will block the current thread
server.start().unwrap();
}
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server: Server = Server::<()>::new("localhost", 8080);
// Define 404 page
// This route will run for all requests but because any other route
// will take priority it will only run when no other route is defined.
/* PRIO 0 */
server.route(Method::ANY, "**", |_req| {
Response::new()
.status(Status::NotFound)
.text("The page you are looking for does not exist :/")
.content(Content::TXT)
});
// Define a route
// As this is defined last, it will take a higher priority
/* PRIO 1 */
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// Now goto http://localhost:8080/ and you should see "Hello World"
// But if you go to http://localhost:8080/somthing-else you should see the 404 page
// Start the server
// This will block the current thread
server.start().unwrap();
}
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
fn exec(&self) {
// Create a new Server instance on localhost port 8080
let mut server = Server::<()>::new("localhost", 8080);
// Define a handler for GET "/"
server.route(Method::GET, "/", |_req| {
Response::new().text("Hello World!").content(Content::TXT)
});
// For this example, we'll limit requests to 1 every 2 seconds
// Make a new Ratelimater
// Default Limit is 10
// Default Timeout is 60 sec
RateLimiter::new()
// Override the Limit to 1
.limit(1)
// Override the timeout to 2
.timeout(2)
// Override the Handler
.handler(Box::new(|_req| {
Some(
Response::new()
.status(Status::TooManyRequests)
.text("AHHHH!!! Too Many Requests")
.content(Content::TXT),
)
}))
// Attach to the server
.attach(&mut server);
// Now if you goto http://localhost:8080/ and reload a bunch of times,
// you'll see the rate limiter kicking in.
// Start the server
// This will block the current thread
server.start().unwrap();
}