summaryrefslogtreecommitdiffhomepage
path: root/examples/rust/echo-request-wbody/src/lib.rs
blob: 1825874d9d4443aea632118f370b64e6eed88606 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
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
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
142
143
144
145
146
147
148
149
150
151
152
/* SPDX-License-Identifier: Apache-2.0 */

/*
 * Copyright (C) Andrew Clayton
 * Copyright (C) Timo Stark
 * Copyright (C) F5, Inc.
 */

use unit_wasm::rusty::*;

use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ptr::null_mut;

use serde_json::{Result, Value};

// Buffer of some size to store the copy of the request
static mut REQUEST_BUF: *mut u8 = null_mut();

#[no_mangle]
pub extern "C" fn uwr_module_end_handler() {
    unsafe {
        uwr_free(REQUEST_BUF);
    }
}

#[no_mangle]
pub extern "C" fn uwr_module_init_handler() {
    unsafe {
        REQUEST_BUF = uwr_malloc(uwr_mem_get_init_size());
    }
}

pub extern "C" fn hdr_iter_func(
    ctx: *mut luw_ctx_t,
    name: *const c_char,
    value: *const c_char,
    _data: *mut c_void,
) -> bool {
    uwr_write_str!(ctx, "{} = {}\n", C2S!(name), C2S!(value));

    return true;
}

#[no_mangle]
pub extern "C" fn uwr_request_handler(addr: *mut u8) -> i32 {
    // Declare a 0-initialised context structure

    let ctx = &mut UWR_CTX_INITIALIZER();
    // get the HTTP Method 
    let method = uwr_get_http_method(ctx);
   
    // Initialise the context structure.
    //
    // addr is the address of the previously allocated memory shared
    // between the module and unit.
    //
    // The response data will be stored @ addr + offset (of 4096 bytes).
    // This will leave some space for the response headers.
    uwr_init_ctx(ctx, addr, 4096);

    // Set where we will copy the request into
    unsafe {
        uwr_set_req_buf(ctx, &mut REQUEST_BUF, LUW_SRB_NONE);
    }

    // Get request body
    let request_body: &CStr;
    let mystring: String;

    //if method == "POST" || method == "PUT" {
    request_body = unsafe { CStr::from_ptr(uwr_get_http_content(ctx) as *mut i8) };
    // Get copy-on-write Cow<'_, str>, then guarantee a freshly-owned String allocation
    mystring = String::from_utf8_lossy(request_body.to_bytes()).to_string();
   

    fn parser(data: String) -> Result<Value> {
      let json: Value = serde_json::from_str(&data)?;
      // Like a return statement in case of no error
      Ok(json)
    }

    let json = parser(mystring);
    match json {
      Ok(result) => { uwr_write_str!(ctx, "Message: {}\n", result["message"]);},
      Err(error) => println!("{}", error),
    }
    
    //}
    
    // Define the Response Body Text.
    uwr_write_str!(
        ctx,
        " * Welcome to WebAssembly in Rust on Unit! \
            [libunit-wasm ({}.{}.{}/{:#010x})] *\n\n",
        LUW_VERSION_MAJOR,
        LUW_VERSION_MINOR,
        LUW_VERSION_PATCH,
        LUW_VERSION_NUMBER,
    );

    uwr_write_str!(ctx, "[Request Info]\n");
    uwr_write_str!(ctx, "REQUEST_PATH = {}\n", uwr_get_http_path(ctx));
    uwr_write_str!(ctx, "METHOD       = {}\n", uwr_get_http_method(ctx));
    uwr_write_str!(ctx, "VERSION      = {}\n", uwr_get_http_version(ctx));
    uwr_write_str!(ctx, "QUERY        = {}\n", uwr_get_http_query(ctx));
    uwr_write_str!(ctx, "REMOTE       = {}\n", uwr_get_http_remote(ctx));
    uwr_write_str!(ctx, "LOCAL_ADDR   = {}\n", uwr_get_http_local_addr(ctx));
    uwr_write_str!(ctx, "LOCAL_PORT   = {}\n", uwr_get_http_local_port(ctx));
    uwr_write_str!(ctx, "SERVER_NAME  = {}\n", uwr_get_http_server_name(ctx));

    uwr_write_str!(ctx, "\n[Request Headers]\n");

    uwr_http_hdr_iter(ctx, Some(hdr_iter_func), null_mut());

    if method == "POST" || method == "PUT" {
        uwr_write_str!(ctx, "\n[{} data]\n", method);
        uwr_mem_write_buf(
            ctx,
            uwr_get_http_content(ctx),
            uwr_get_http_content_len(ctx),
        );
        uwr_write_str!(ctx, "\n");
    }

    // Init Response Headers
    //
    // Needs the context, number of headers about to add as well as
    // the offset where to store the headers. In this case we are
    // storing the response headers at the beginning of our shared
    // memory at offset 0.
    uwr_http_init_headers(ctx, 2, 0);
    uwr_http_add_header(ctx, 0, "Content-Type", "text/plain");
    uwr_http_add_header(
        ctx,
        1,
        "Content-Length",
        &format!("{}", uwr_get_response_data_size(ctx)),
    );

    // This calls nxt_wasm_send_headers() in Unit
    uwr_http_send_headers(ctx);

    // This calls nxt_wasm_send_response() in Unit
    uwr_http_send_response(ctx);

    // This calls nxt_wasm_response_end() in Unit
    uwr_http_response_end();

    return 0;
}