Struct Unit

Source
pub struct Unit { /* private fields */ }
Expand description

The Unit application context.

This object wraps the libunit library, which talks to the Unit server over shared memory and a unix socket in order to receive data about requests.

This object is not Send nor Sync, and cannot be sent to other threads.

However, multiple objects of this type may be created; additional Unit objects will automatically be linked to the first through a global mutex, and will be able to receive and process requests in other threads.

The first context is internally wrapped in an Arc, shared among all instances Unit and will be deallocated when the last Unit object is dropped.

Implementations§

Source§

impl Unit

Source

pub fn new() -> Result<Self, UnitInitError>

Create a new Unit context capable of receiving and handling requests on the current thread.

If called after a previous Unit was constructed but already received a QUIT event from the Unit server, this will return a no-op Unit instance whose Unit::run method will immediately return.

If called after a previous Unit failed to initialize, this will return the same initialization failure.

Examples found in repository?
examples/request_info.rs (line 9)
8fn main() {
9    let mut unit = Unit::new().unwrap();
10
11    unit.set_request_handler(request_handler);
12
13    unit.run();
14}
More examples
Hide additional examples
examples/hello_world.rs (line 6)
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}
examples/http_adapter.rs (line 8)
7fn main() {
8    let mut unit = Unit::new().unwrap();
9
10    unit.set_request_handler(HttpHandler::new(|req: Request<Vec<u8>>| {
11        let body = format!("Hello world!\n\nBody length: {}\n", req.body().len());
12
13        // The Unit server redirects stdout/stderr to the server log.
14        eprintln!("Received reqest for: {}", req.uri().path());
15
16        if req.uri().path() == "/panic" {
17            // The HttpHandler converts panics into 501 errors. This imposes an
18            // UnwindSafe restriction on the request handler.
19            panic!("The /panic path panics!")
20        }
21
22        let response = Response::builder()
23            .header("Content-Type", "text/plain")
24            .body(body.into_bytes())
25            .unwrap();
26
27        Ok(response)
28    }));
29
30    unit.run();
31}
examples/multi_threaded.rs (line 30)
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}
Source

pub fn set_request_handler(&mut self, f: impl UnitService + 'static)

Set a request handler for the Unit application.

The handler must be an object that implements the UnitService trait.

This trait is automatically implemented for functions or lambda functions that take a Request object and return a UnitResult<()>.

Examples found in repository?
examples/request_info.rs (line 11)
8fn main() {
9    let mut unit = Unit::new().unwrap();
10
11    unit.set_request_handler(request_handler);
12
13    unit.run();
14}
More examples
Hide additional examples
examples/hello_world.rs (lines 8-14)
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}
examples/http_adapter.rs (lines 10-28)
7fn main() {
8    let mut unit = Unit::new().unwrap();
9
10    unit.set_request_handler(HttpHandler::new(|req: Request<Vec<u8>>| {
11        let body = format!("Hello world!\n\nBody length: {}\n", req.body().len());
12
13        // The Unit server redirects stdout/stderr to the server log.
14        eprintln!("Received reqest for: {}", req.uri().path());
15
16        if req.uri().path() == "/panic" {
17            // The HttpHandler converts panics into 501 errors. This imposes an
18            // UnwindSafe restriction on the request handler.
19            panic!("The /panic path panics!")
20        }
21
22        let response = Response::builder()
23            .header("Content-Type", "text/plain")
24            .body(body.into_bytes())
25            .unwrap();
26
27        Ok(response)
28    }));
29
30    unit.run();
31}
examples/multi_threaded.rs (lines 35-60)
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}
Source

pub fn run(&mut self)

Enter the main event loop, handling requests on this thread until the Unit server exits or requests a restart.

This may be executed in parallel with other threads that call Unit::run()

Examples found in repository?
examples/request_info.rs (line 13)
8fn main() {
9    let mut unit = Unit::new().unwrap();
10
11    unit.set_request_handler(request_handler);
12
13    unit.run();
14}
More examples
Hide additional examples
examples/hello_world.rs (line 16)
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}
examples/http_adapter.rs (line 30)
7fn main() {
8    let mut unit = Unit::new().unwrap();
9
10    unit.set_request_handler(HttpHandler::new(|req: Request<Vec<u8>>| {
11        let body = format!("Hello world!\n\nBody length: {}\n", req.body().len());
12
13        // The Unit server redirects stdout/stderr to the server log.
14        eprintln!("Received reqest for: {}", req.uri().path());
15
16        if req.uri().path() == "/panic" {
17            // The HttpHandler converts panics into 501 errors. This imposes an
18            // UnwindSafe restriction on the request handler.
19            panic!("The /panic path panics!")
20        }
21
22        let response = Response::builder()
23            .header("Content-Type", "text/plain")
24            .body(body.into_bytes())
25            .unwrap();
26
27        Ok(response)
28    }));
29
30    unit.run();
31}
examples/multi_threaded.rs (line 62)
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}

Trait Implementations§

Source§

impl Drop for Unit

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl Freeze for Unit

§

impl !RefUnwindSafe for Unit

§

impl !Send for Unit

§

impl !Sync for Unit

§

impl Unpin for Unit

§

impl !UnwindSafe for Unit

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

fn into(self) -> U

Calls U::from(self).

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

Source§

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

Source§

type Error = Infallible

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

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

Performs the conversion.
Source§

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

Source§

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

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

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

Performs the conversion.