Skip to content

Latest commit

 

History

History

rest

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Caryatid REST server example

This example demonstrates adding a REST server to a Caryatid framework, and using the message subscription system to implement request routing as you might do explicitly in Axum or Express.

The example configuration sets up two REST server endpoints, on ports 4340 and 4341. It also creates two versions of a 'Hello world!' responder, which register on the rest.get.hello and rest2.get.hello topics:

[module.rest-server]
address = "127.0.0.1"
port = 4340

[module.rest-server-2]
class = "rest-server"
topic = "rest2"
port = 4341

[module.rest-hello-world]
topic = "rest.get.hello"

[module.rest-hello-world-2]
class = "rest-hello-world"
topic = "rest2.get.hello"

How to run it

$ cd examples/rest
$ cargo run

Then go to localhost:4340/hello in your browser. Try other URL paths (which will fail after a 5 second timeout) and also port 4341.

Points of interest

The process uses typed messages (as explained in the typed example), and defines its Message enum in message.rs:

pub enum Message {
    None(()),                   // Just so we have a simple default
    RESTRequest(RESTRequest),   // REST request
    RESTResponse(RESTResponse), // REST response
}

It then implements From and GetRESTResponse to create and unpack this Message from/to the RESTRequest and RESTResponse.

The process is defined in main.rs using the Message type:

    let mut process = Process::<Message>::create(config).await;

and likewise the RESTServer - as a generic module which can be used by any application, it needs to know the top-level message type in use:

    RESTServer::<Message>::register(&mut process);

See the RESTServer documentation for more details.

To respond to the REST request, we define a RESTHelloWorld responder. This registers a lambda as the handler for the configured topic:

        context.message_bus.handle(&topic, |message: Arc<Message>| {
            let response = match message.as_ref() {
                Message::RESTRequest(request) => {
                    info!("REST hello world received {} {}", request.method, request.path);
                    RESTResponse {
                        code: 200,
                        body: "Hello, world!".to_string()
                    }
                },
                _ => {
                    error!("Unexpected message type {:?}", message);
                    RESTResponse {
                        code: 500,
                        body: "Unexpected message in REST request".to_string() }
                }
            };

            future::ready(Arc::new(Message::RESTResponse(response)))
        })?;

Note that because we're using a synchronous lambda we need to manually return the future for the result.