pub struct Request<'a> { /* private fields */ }
Expand description
A request received by the NGINX Unit server.
This object can be used to inspect the properties and headers of the request, and send a response back to the client.
Implementations§
Source§impl<'a> Request<'a>
impl<'a> Request<'a>
Sourcepub fn create_response(
&'a self,
status_code: u16,
max_fields_count: usize,
max_response_size: usize,
) -> UnitResult<Response<'a>>
pub fn create_response( &'a self, status_code: u16, max_fields_count: usize, max_response_size: usize, ) -> UnitResult<Response<'a>>
Allocate a buffer for the initial response, capable of containing at
most max_fields_count
fields (headers), and at most
max_response_size
bytes for the field names, field values, and
response content combined.
The buffer can be filled and sent using the methods on the returned
Response
.
The buffer can be resized with Response::realloc
.
Sourcepub fn send_response(
&self,
status_code: u16,
headers: &[(impl AsRef<[u8]>, impl AsRef<[u8]>)],
body: impl AsRef<[u8]>,
) -> UnitResult<()>
pub fn send_response( &self, status_code: u16, headers: &[(impl AsRef<[u8]>, impl AsRef<[u8]>)], body: impl AsRef<[u8]>, ) -> UnitResult<()>
Send an initial response to the client.
This is a convenience method that calls the Request::create_response
,
Response::add_field
, Response::add_content
, and
Response::send
methods.
§Panic
This method will panic if the header name is longer than u8::MAX
bytes, or if the header value is longer than u32::MAX
.
Examples found in repository?
5fn main() {
6 let mut unit = Unit::new().unwrap();
7
8 unit.set_request_handler(|req: Request| {
9 let headers = &[("Content-Type", "text/plain")];
10 let body = "Hello world!\n";
11 req.send_response(200, headers, body)?;
12
13 Ok(())
14 });
15
16 unit.run();
17}
More examples
29fn worker(thread_id: i32, global_visits: Arc<AtomicI32>) {
30 let mut unit = Unit::new().unwrap();
31
32 // Thread state, available through a mutable, unique reference.
33 let mut thread_visits = 0;
34
35 unit.set_request_handler(move |req: Request| {
36 if req.path() == "/panic" {
37 // This library supports safely forwarding panics through the FFI.
38 panic!("The /panic path panics!")
39 }
40
41 let headers = &[("Content-Type", "text/plain")];
42 let body = "Hello world!\n";
43 req.send_response(200, headers, body)?;
44 thread_visits += 1;
45 global_visits.fetch_add(1, Ordering::Release);
46
47 req.send_chunk_with_buffer(4096, |buf| {
48 writeln!(
49 buf,
50 "Thread {} visits: {} (global visits: {})",
51 thread_id,
52 thread_visits,
53 global_visits.load(Ordering::Acquire),
54 )
55 .unwrap();
56 Ok(())
57 })?;
58
59 Ok(())
60 });
61
62 unit.run();
63}
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn write_chunks(&'a self, chunk_size: usize) -> Result<BodyWriter<'a>>
pub fn write_chunks(&'a self, chunk_size: usize) -> Result<BodyWriter<'a>>
Allocate and send additional response chunks to the client, using a writer to copy data into the chunks.
A chunk will be immediately sent to the client once the writer’s memory
buffer reaches chunk_size
, or flush()
is
called on the writer.
The writer will also flush when dropped, but may panic in case of errors.
§Panic
Panics if flushing was not successful when flushing during a drop. It is
recommended to manually call flush()
, or use
the Request::send_chunks_with_writer()
method.
Sourcepub fn send_chunks_with_writer<T>(
&'a self,
chunk_size: usize,
f: impl FnOnce(&mut BodyWriter<'a>) -> Result<T>,
) -> UnitResult<T>
pub fn send_chunks_with_writer<T>( &'a self, chunk_size: usize, f: impl FnOnce(&mut BodyWriter<'a>) -> Result<T>, ) -> UnitResult<T>
Allocate and send additional response chunks to the client.
This is similar to write_chunks()
, but will
also flush the writer before returning, convert the result into a
UnitError
, and log the error.
This is useful to prevent errors from being silently ignored if the writer needs to flush while being dropped.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn send_chunk_with_buffer<T>(
&self,
size: usize,
f: impl FnOnce(&mut &mut [u8]) -> UnitResult<T>,
) -> UnitResult<T>
pub fn send_chunk_with_buffer<T>( &self, size: usize, f: impl FnOnce(&mut &mut [u8]) -> UnitResult<T>, ) -> UnitResult<T>
Send another chunk of bytes for this request’s response. The bytes will be immediately sent to the client.
This method allocates a buffer in Unit’s shared memory region, and calls a user function to fill it.
The user function receives a &mut &mut [u8]
slice, and the write!
macro can be used to advance the start position of the slice. Only the
bytes between the original start and the new start positions will be
sent, and the rest will be discarded.
Examples found in repository?
29fn worker(thread_id: i32, global_visits: Arc<AtomicI32>) {
30 let mut unit = Unit::new().unwrap();
31
32 // Thread state, available through a mutable, unique reference.
33 let mut thread_visits = 0;
34
35 unit.set_request_handler(move |req: Request| {
36 if req.path() == "/panic" {
37 // This library supports safely forwarding panics through the FFI.
38 panic!("The /panic path panics!")
39 }
40
41 let headers = &[("Content-Type", "text/plain")];
42 let body = "Hello world!\n";
43 req.send_response(200, headers, body)?;
44 thread_visits += 1;
45 global_visits.fetch_add(1, Ordering::Release);
46
47 req.send_chunk_with_buffer(4096, |buf| {
48 writeln!(
49 buf,
50 "Thread {} visits: {} (global visits: {})",
51 thread_id,
52 thread_visits,
53 global_visits.load(Ordering::Acquire),
54 )
55 .unwrap();
56 Ok(())
57 })?;
58
59 Ok(())
60 });
61
62 unit.run();
63}
Sourcepub fn read_body(&self, target: &mut [u8]) -> usize
pub fn read_body(&self, target: &mut [u8]) -> usize
Copy bytes from the request body into the target buffer and return the number of bytes written.
If the buffer is smaller than the contents of the body, the contents will be truncated to the size of the buffer.
Sourcepub fn body(&self) -> BodyReader<'a> ⓘ
pub fn body(&self) -> BodyReader<'a> ⓘ
Create a reader that implements the Read
trait,
which will read from the request body in a blocking manner.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn fields(&self) -> impl Iterator<Item = (&str, &str)>
pub fn fields(&self) -> impl Iterator<Item = (&str, &str)>
Create an interator over all header (name, value) tuples.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn method(&self) -> &str
pub fn method(&self) -> &str
Return the method of the request (e.g. “GET”).
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn version(&self) -> &str
pub fn version(&self) -> &str
Return the protocol version of the request (e.g. “HTTP/1.1”).
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn remote(&self) -> &str
pub fn remote(&self) -> &str
Return the remote IP address of the client.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn local(&self) -> &str
pub fn local(&self) -> &str
Return the local IP address of the server.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn server_name(&self) -> &str
pub fn server_name(&self) -> &str
Return the host name of the server.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn target(&self) -> &str
pub fn target(&self) -> &str
Return the combined URI path and query string.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn path(&self) -> &str
pub fn path(&self) -> &str
Return the URI path.
Examples found in repository?
29fn worker(thread_id: i32, global_visits: Arc<AtomicI32>) {
30 let mut unit = Unit::new().unwrap();
31
32 // Thread state, available through a mutable, unique reference.
33 let mut thread_visits = 0;
34
35 unit.set_request_handler(move |req: Request| {
36 if req.path() == "/panic" {
37 // This library supports safely forwarding panics through the FFI.
38 panic!("The /panic path panics!")
39 }
40
41 let headers = &[("Content-Type", "text/plain")];
42 let body = "Hello world!\n";
43 req.send_response(200, headers, body)?;
44 thread_visits += 1;
45 global_visits.fetch_add(1, Ordering::Release);
46
47 req.send_chunk_with_buffer(4096, |buf| {
48 writeln!(
49 buf,
50 "Thread {} visits: {} (global visits: {})",
51 thread_id,
52 thread_visits,
53 global_visits.load(Ordering::Acquire),
54 )
55 .unwrap();
56 Ok(())
57 })?;
58
59 Ok(())
60 });
61
62 unit.run();
63}
More examples
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}
Sourcepub fn query(&self) -> &str
pub fn query(&self) -> &str
Return the URI query string.
Examples found in repository?
16fn request_handler(req: Request) -> UnitResult<()> {
17 // Create and send a response.
18 let headers = &[("Content-Type", "text/plain")];
19 req.send_response(200, headers, "Hello world!\n")?;
20
21 // NGINX Unit uses "Transfer-Encoding: chunked" by default, and can send
22 // additional chunks after the initial response was already sent to the
23 // client.
24 req.send_chunks_with_writer(4096, |w| {
25 write!(w, "Request data:\n")?;
26 write!(w, " Method: {}\n", req.method())?;
27 write!(w, " Protocol: {}\n", req.version())?;
28 write!(w, " Remote addr: {}\n", req.remote())?;
29 write!(w, " Local addr: {}\n", req.local())?;
30 write!(w, " Server name: {}\n", req.server_name())?;
31 write!(w, " Target: {}\n", req.target())?;
32 write!(w, " Path: {}\n", req.path())?;
33 write!(w, " Query: {}\n", req.query())?;
34 write!(w, " Fields:\n")?;
35 for (name, value) in req.fields() {
36 write!(w, " {}: {}\n", name, value).unwrap();
37 }
38 write!(w, " Body:\n ").unwrap();
39
40 w.copy_from_reader(req.body())?;
41
42 Ok(())
43 })?;
44
45 Ok(())
46}