Welcome to the new Golem Cloud Docs! 👋
Documentation
Request Response Transformation using Rib

Using Rib in API definition

Rib can be used in the API definition to define the response of an API endpoint. The response field in the API definition is a Rib script that is executed to generate the response for the API endpoint.

With Rib, it is also possible to lookup values from the request context, such as request path, query variables, headers, and JWT token claims.

Response Mapping

The response field under each binding is written using Rib to call the worker function, manipulate its results, and return a value that's understandable for each protocol we use. If the protocol is HTTP, the result of Rib is converted to an HTTP response.

Example: Below is a Rib script where the result type is a record with two fields: status and body, along with headers, which correspond to the status code, response headers, and body in an HTTP response.

Terminal
 
 let result = golem:it/api.{get-cart-contents}();
 { status: 200u64, body: result, headers: { Content-Type: "application/json" } }
 

Example API definition with more Rib scripts

Here is a more complex example of an API definition with multiple routes and and more complex Rib scripts under response field. Certain fields are omitted for brevity.

id: my-shopping-cart-v2
draft: true
version: 2.0.11
routes:
  - method: Get
    path: "/{user-id}/get-cart-contents"
    binding:
      response: |
        let result = golem:it/api.{get-cart-contents}();
        {status: 200u64, body: result}
  - method: Post
    path: "/{user-id}/initialize-cart"
    binding:
      response: |
        let empty: list<u16> = [];
        golem:it/api.{initialize-cart}(request.path.user-id);
        {status: 200u64, body: empty}
  - method: Post
    path: "/{user-id}/add-item"
    binding:
      response: |
        let quantity: f64 = request.body.quantity;
        let product_id: u64 = request.body.product-id;
        let name: string = request.body.name;
        let price: f64 = request.body.price;
        let input = {product-id: product_id, name: name, price: price, quantity: quantity};
        golem:it/api.{add-item}(input);
        {status: 200u64, body: success}
  - method: Post
    path: "/{user-id}/checkout"
    binding:
      response: |
        let result = golem:it/api.{checkout}();
        let status = 200u64;
        let body =  match result { success(resp) => resp.order-id, error(msg) => msg };
        {status: status, body: body}

Most of the above examples are self explanatory, but worth pointing out a few details.

Passing parameters to worker functions

For example, in the initialize-cart endpoint, we pass the user-id from the request path to the worker function.

Terminal
 
golem:it/api.{initialize-cart}(request.path.user-id)
 

Here Rib compiler knows the requirement of initialize-cart function and infers that request.path.user-id should be u64. This is a hint, that Rib is aware of the types in the code. In places where it find hard to infer these types, you may face some compile time errors (when uploading API definition), and the best solution is to be explicit about types. For example

Terminal
let user_id: u64 = request.path.user-id;
golem:it/api.{initialize-cart}(user_id)
 

Handling response from worker functions

There are various possibilities here to manipulate the data using Rib language, such as selecting only a particular field from the result of the function invocation. Say for example, the result is a WASM result which can be ok or err. In this case you can have a complex Rib expression as below

Terminal
let result = golem:it/api.{get-cart-contents}();
 
let response_status = match result {
  ok(_) => 200u32,
  err(_) => 400u32
};
 
let response_body = match result {
  ok(result) => result,
  err(msg) => msg
}
 
{status: response_status, body: response_body}
 

The result of the Rib expression is whatever the result of the last line/expression in the above Rib program, similar to many programming languages. Note, the last line of Rib is not ending with a ;.

Lookup up values from the request context

Rib allow to look up the values of request path or query variables using request.path.* syntax. For request body, you can use request.body.* syntax. Similarly for headers it is request.headers.* If security is enabled, then you can also look up the JWT token claims using request.auth.*, such as request.auth.email to get the email of the user. This is already shown in most of the examples above.