You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ki...@apache.org on 2022/12/08 09:28:54 UTC

[trafficserver] branch master updated: Bug fix and add example for Wasm plugin (#9233)

This is an automated email from the ASF dual-hosted git repository.

kichan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 7344d7bf3 Bug fix and add example for Wasm plugin (#9233)
7344d7bf3 is described below

commit 7344d7bf31b81ebe2547d6ea7d87f28abdc7ac9f
Author: Kit Chan <ki...@apache.org>
AuthorDate: Thu Dec 8 01:28:45 2022 -0800

    Bug fix and add example for Wasm plugin (#9233)
    
    * Fixes for Wasm plugin and a TinyGo example
    
    * fix typos on tinygo example README
    
    * Fix clang-format error
    
    * Update README.md
---
 plugins/experimental/wasm/ats_context.cc           | 115 +++++++++++----------
 plugins/experimental/wasm/ats_context.h            |  92 ++++++++---------
 .../experimental/wasm/examples/tinygo/README.md    |  13 +++
 .../experimental/wasm/examples/tinygo/plugin.yaml  |  18 ++++
 4 files changed, 139 insertions(+), 99 deletions(-)

diff --git a/plugins/experimental/wasm/ats_context.cc b/plugins/experimental/wasm/ats_context.cc
index 7bd401b1a..ca31a71ee 100644
--- a/plugins/experimental/wasm/ats_context.cc
+++ b/plugins/experimental/wasm/ats_context.cc
@@ -388,6 +388,12 @@ Context::getCurrentTimeNanoseconds()
   return TShrtime();
 }
 
+uint64_t
+Context::getMonotonicTimeNanoseconds()
+{
+  return TShrtime();
+}
+
 std::string_view
 Context::getConfiguration()
 {
@@ -496,17 +502,17 @@ Context::getMetric(uint32_t metric_id, uint64_t *value_ptr)
 WasmResult
 Context::getProperty(std::string_view path, std::string *result)
 {
-  if (path == p_plugin_root_id) {
+  if (path.substr(0, p_plugin_root_id.size()) == p_plugin_root_id) {
     *result = this->plugin_->root_id_;
     TSDebug(WASM_DEBUG_TAG, "[%s] looking for plugin_root_id: %.*s", __FUNCTION__, static_cast<int>((*result).size()),
             (*result).data());
     return WasmResult::Ok;
-  } else if (path == p_plugin_name) {
+  } else if (path.substr(0, p_plugin_name.size()) == p_plugin_name) {
     *result = this->plugin_->name_;
     TSDebug(WASM_DEBUG_TAG, "[%s] looking for plugin_name: %.*s", __FUNCTION__, static_cast<int>((*result).size()),
             (*result).data());
     return WasmResult::Ok;
-  } else if (path == p_plugin_vm_id) {
+  } else if (path.substr(0, p_plugin_vm_id.size()) == p_plugin_vm_id) {
     *result = this->plugin_->vm_id_;
     TSDebug(WASM_DEBUG_TAG, "[%s] looking for plugin_vm_id: %.*s", __FUNCTION__, static_cast<int>((*result).size()),
             (*result).data());
@@ -515,7 +521,7 @@ Context::getProperty(std::string_view path, std::string *result)
     *result = pv_empty;
     TSDebug(WASM_DEBUG_TAG, "[%s] looking for node property: empty string for now", __FUNCTION__);
     return WasmResult::Ok;
-  } else if (path == p_source_address) {
+  } else if (path.substr(0, p_source_address.size()) == p_source_address) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -524,7 +530,7 @@ Context::getProperty(std::string_view path, std::string *result)
     client_ip                        = TSHttpTxnClientAddrGet(txnp_);
     print_address(client_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_source_port) {
+  } else if (path.substr(0, p_source_port.size()) == p_source_port) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -533,7 +539,7 @@ Context::getProperty(std::string_view path, std::string *result)
     client_ip                        = TSHttpTxnClientAddrGet(txnp_);
     print_port(client_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_destination_address) {
+  } else if (path.substr(0, p_destination_address.size()) == p_destination_address) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -542,7 +548,7 @@ Context::getProperty(std::string_view path, std::string *result)
     local_ip                        = TSHttpTxnIncomingAddrGet(txnp_);
     print_address(local_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_destination_port) {
+  } else if (path.substr(0, p_destination_port.size()) == p_destination_port) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -551,7 +557,7 @@ Context::getProperty(std::string_view path, std::string *result)
     local_ip                        = TSHttpTxnIncomingAddrGet(txnp_);
     print_port(local_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_connection_mtls) {
+  } else if (path.substr(0, p_connection_mtls.size()) == p_connection_mtls) {
     bool m = false;
     if (txnp_ == nullptr) {
       result->assign(reinterpret_cast<const char *>(&m), sizeof(bool));
@@ -568,7 +574,7 @@ Context::getProperty(std::string_view path, std::string *result)
     }
     result->assign(reinterpret_cast<const char *>(&m), sizeof(bool));
     return WasmResult::Ok;
-  } else if (path == p_connection_requested_server_name) {
+  } else if (path.substr(0, p_connection_requested_server_name.size()) == p_connection_requested_server_name) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -584,7 +590,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_connection_tls_version) {
+  } else if (path.substr(0, p_connection_tls_version.size()) == p_connection_tls_version) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -599,7 +605,7 @@ Context::getProperty(std::string_view path, std::string *result)
 
     result->assign(ssl_protocol);
     return WasmResult::Ok;
-  } else if (path == p_connection_subject_local_certificate) {
+  } else if (path.substr(0, p_connection_subject_local_certificate.size()) == p_connection_subject_local_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -616,7 +622,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_connection_subject_peer_certificate) {
+  } else if (path.substr(0, p_connection_subject_peer_certificate.size()) == p_connection_subject_peer_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -633,7 +639,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_connection_dns_san_local_certificate) {
+  } else if (path.substr(0, p_connection_dns_san_local_certificate.size()) == p_connection_dns_san_local_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -650,7 +656,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_connection_dns_san_peer_certificate) {
+  } else if (path.substr(0, p_connection_dns_san_peer_certificate.size()) == p_connection_dns_san_peer_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -667,7 +673,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_connection_uri_san_local_certificate) {
+  } else if (path.substr(0, p_connection_uri_san_local_certificate.size()) == p_connection_uri_san_local_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -684,7 +690,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_connection_uri_san_peer_certificate) {
+  } else if (path.substr(0, p_connection_uri_san_peer_certificate.size()) == p_connection_uri_san_peer_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -701,7 +707,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_upstream_address) {
+  } else if (path.substr(0, p_upstream_address.size()) == p_upstream_address) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -710,7 +716,7 @@ Context::getProperty(std::string_view path, std::string *result)
     server_ip                        = TSHttpTxnServerAddrGet(txnp_);
     print_address(server_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_upstream_port) {
+  } else if (path.substr(0, p_upstream_port.size()) == p_upstream_port) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -719,7 +725,7 @@ Context::getProperty(std::string_view path, std::string *result)
     server_ip                        = TSHttpTxnClientAddrGet(txnp_);
     print_port(server_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_upstream_local_address) {
+  } else if (path.substr(0, p_upstream_local_address.size()) == p_upstream_local_address) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -728,7 +734,7 @@ Context::getProperty(std::string_view path, std::string *result)
     local_ip                        = TSHttpTxnOutgoingAddrGet(txnp_);
     print_address(local_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_upstream_local_port) {
+  } else if (path.substr(0, p_upstream_local_port.size()) == p_upstream_local_port) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -737,7 +743,7 @@ Context::getProperty(std::string_view path, std::string *result)
     local_ip                        = TSHttpTxnOutgoingAddrGet(txnp_);
     print_port(local_ip, result);
     return WasmResult::Ok;
-  } else if (path == p_upstream_tls_version) {
+  } else if (path.substr(0, p_upstream_tls_version.size()) == p_upstream_tls_version) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -752,7 +758,7 @@ Context::getProperty(std::string_view path, std::string *result)
 
     result->assign(ssl_protocol);
     return WasmResult::Ok;
-  } else if (path == p_upstream_subject_local_certificate) {
+  } else if (path.substr(0, p_upstream_subject_local_certificate.size()) == p_upstream_subject_local_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -769,7 +775,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_upstream_subject_peer_certificate) {
+  } else if (path.substr(0, p_upstream_subject_peer_certificate.size()) == p_upstream_subject_peer_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -786,7 +792,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_upstream_dns_san_local_certificate) {
+  } else if (path.substr(0, p_upstream_dns_san_local_certificate.size()) == p_upstream_dns_san_local_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -803,7 +809,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_upstream_dns_san_peer_certificate) {
+  } else if (path.substr(0, p_upstream_dns_san_peer_certificate.size()) == p_upstream_dns_san_peer_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -820,7 +826,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_upstream_uri_san_local_certificate) {
+  } else if (path.substr(0, p_upstream_uri_san_local_certificate.size()) == p_upstream_uri_san_local_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -837,7 +843,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_upstream_uri_san_peer_certificate) {
+  } else if (path.substr(0, p_upstream_uri_san_peer_certificate.size()) == p_upstream_uri_san_peer_certificate) {
     if (txnp_ == nullptr) {
       *result = pv_empty;
       return WasmResult::Ok;
@@ -854,7 +860,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_path) {
+  } else if (path.substr(0, p_request_path.size()) == p_request_path) {
     TSMBuffer bufp    = nullptr;
     TSMLoc hdr_loc    = nullptr;
     TSMLoc url_loc    = nullptr;
@@ -885,7 +891,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_url_path) {
+  } else if (path.substr(0, p_request_url_path.size()) == p_request_url_path) {
     TSMBuffer bufp   = nullptr;
     TSMLoc hdr_loc   = nullptr;
     TSMLoc url_loc   = nullptr;
@@ -906,7 +912,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_host) {
+  } else if (path.substr(0, p_request_host.size()) == p_request_host) {
     TSMBuffer bufp   = nullptr;
     TSMLoc hdr_loc   = nullptr;
     TSMLoc url_loc   = nullptr;
@@ -946,7 +952,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_scheme) {
+  } else if (path.substr(0, p_request_scheme.size()) == p_request_scheme) {
     TSMBuffer bufp     = nullptr;
     TSMLoc hdr_loc     = nullptr;
     TSMLoc url_loc     = nullptr;
@@ -966,7 +972,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_method) {
+  } else if (path.substr(0, p_request_method.size()) == p_request_method) {
     TSMBuffer bufp     = nullptr;
     TSMLoc hdr_loc     = nullptr;
     const char *method = nullptr;
@@ -980,7 +986,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_query) {
+  } else if (path.substr(0, p_request_query.size()) == p_request_query) {
     TSMBuffer bufp    = nullptr;
     TSMLoc hdr_loc    = nullptr;
     TSMLoc url_loc    = nullptr;
@@ -1000,7 +1006,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_referer) {
+  } else if (path.substr(0, p_request_referer.size()) == p_request_referer) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     if (TSHttpTxnClientReqGet(txnp_, &bufp, &hdr_loc) == TS_SUCCESS) {
@@ -1010,7 +1016,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_useragent) {
+  } else if (path.substr(0, p_request_useragent.size()) == p_request_useragent) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     if (TSHttpTxnClientReqGet(txnp_, &bufp, &hdr_loc) == TS_SUCCESS) {
@@ -1020,7 +1026,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_id) {
+  } else if (path.substr(0, p_request_id.size()) == p_request_id) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     if (TSHttpTxnClientReqGet(txnp_, &bufp, &hdr_loc) == TS_SUCCESS) {
@@ -1047,7 +1053,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_protocol) {
+  } else if (path.substr(0, p_request_protocol.size()) == p_request_protocol) {
     if (TSHttpTxnClientProtocolStackContains(txnp_, "h2") != nullptr) {
       *result = pv_http2;
     } else if (TSHttpTxnClientProtocolStackContains(txnp_, "http/1.0") != nullptr) {
@@ -1058,7 +1064,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_time) {
+  } else if (path.substr(0, p_request_time.size()) == p_request_time) {
     TSHRTime epoch = 0;
     if (TS_SUCCESS == TSHttpTxnMilestoneGet(txnp_, TS_MILESTONE_SM_START, &epoch)) {
       double timestamp = static_cast<double>(epoch) / 1000000000;
@@ -1067,7 +1073,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_request_duration) {
+  } else if (path.substr(0, p_request_duration.size()) == p_request_duration) {
     TSHRTime value = 0;
     TSHRTime epoch = 0;
 
@@ -1080,17 +1086,17 @@ Context::getProperty(std::string_view path, std::string *result)
     }
     *result = pv_empty;
     return WasmResult::Ok;
-  } else if (path == p_request_size) {
+  } else if (path.substr(0, p_request_size.size()) == p_request_size) {
     int64_t bytes = TSHttpTxnClientReqBodyBytesGet(txnp_);
     result->assign(reinterpret_cast<const char *>(&bytes), sizeof(int64_t));
     return WasmResult::Ok;
-  } else if (path == p_request_total_size) {
+  } else if (path.substr(0, p_request_total_size.size()) == p_request_total_size) {
     int h_bytes     = TSHttpTxnClientReqHdrBytesGet(txnp_);
     int64_t b_bytes = TSHttpTxnClientReqBodyBytesGet(txnp_);
     int64_t total   = h_bytes + b_bytes;
     result->assign(reinterpret_cast<const char *>(&total), sizeof(int64_t));
     return WasmResult::Ok;
-  } else if (path == p_response_code) {
+  } else if (path.substr(0, p_response_code.size()) == p_response_code) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     int status     = 0;
@@ -1103,7 +1109,7 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_response_code_details) {
+  } else if (path.substr(0, p_response_code_details.size()) == p_response_code_details) {
     TSMBuffer bufp     = nullptr;
     TSMLoc hdr_loc     = nullptr;
     const char *reason = nullptr;
@@ -1128,11 +1134,11 @@ Context::getProperty(std::string_view path, std::string *result)
       *result = pv_empty;
     }
     return WasmResult::Ok;
-  } else if (path == p_response_size) {
+  } else if (path.substr(0, p_response_size.size()) == p_response_size) {
     int64_t bytes = TSHttpTxnServerRespBodyBytesGet(txnp_);
     result->assign(reinterpret_cast<const char *>(&bytes), sizeof(int64_t));
     return WasmResult::Ok;
-  } else if (path == p_response_total_size) {
+  } else if (path.substr(0, p_response_total_size.size()) == p_response_total_size) {
     int h_bytes     = TSHttpTxnServerRespHdrBytesGet(txnp_);
     int64_t b_bytes = TSHttpTxnServerRespBodyBytesGet(txnp_);
     int64_t total   = h_bytes + b_bytes;
@@ -1148,7 +1154,7 @@ Context::getProperty(std::string_view path, std::string *result)
 WasmResult
 Context::setProperty(std::string_view key, std::string_view serialized_value)
 {
-  if (key == p_request_url_path) {
+  if (key.substr(0, p_request_url_path.size()) == p_request_url_path) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     TSMLoc url_loc = nullptr;
@@ -1168,7 +1174,7 @@ Context::setProperty(std::string_view key, std::string_view serialized_value)
       TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
     }
     return WasmResult::Ok;
-  } else if (key == p_request_host) {
+  } else if (key.substr(0, p_request_host.size()) == p_request_host) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     TSMLoc url_loc = nullptr;
@@ -1181,7 +1187,7 @@ Context::setProperty(std::string_view key, std::string_view serialized_value)
       TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
     }
     return WasmResult::Ok;
-  } else if (key == p_request_scheme) {
+  } else if (key.substr(0, p_request_scheme.size()) == p_request_scheme) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     TSMLoc url_loc = nullptr;
@@ -1194,7 +1200,7 @@ Context::setProperty(std::string_view key, std::string_view serialized_value)
       TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
     }
     return WasmResult::Ok;
-  } else if (key == p_request_method) {
+  } else if (key.substr(0, p_request_method.size()) == p_request_method) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
 
@@ -1203,7 +1209,7 @@ Context::setProperty(std::string_view key, std::string_view serialized_value)
       TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
     }
     return WasmResult::Ok;
-  } else if (key == p_request_query) {
+  } else if (key.substr(0, p_request_query.size()) == p_request_query) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
     TSMLoc url_loc = nullptr;
@@ -1227,7 +1233,7 @@ Context::setProperty(std::string_view key, std::string_view serialized_value)
       TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
     }
     return WasmResult::Ok;
-  } else if (key == p_response_code) {
+  } else if (key.substr(0, p_response_code.size()) == p_response_code) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
 
@@ -1237,7 +1243,7 @@ Context::setProperty(std::string_view key, std::string_view serialized_value)
       TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
     }
     return WasmResult::Ok;
-  } else if (key == p_response_code_details) {
+  } else if (key.substr(0, p_response_code_details.size()) == p_response_code_details) {
     TSMBuffer bufp = nullptr;
     TSMLoc hdr_loc = nullptr;
 
@@ -1272,7 +1278,10 @@ Context::sendLocalResponse(uint32_t response_code, std::string_view body_text, P
   } else {
     TSHttpTxnStatusSet(txnp_, static_cast<TSHttpStatus>(response_code));
 
-    TSHttpTxnErrorBodySet(txnp_, TSstrndup(body_text.data(), body_text.size()), body_text.size(), nullptr); // Defaults to text/html
+    if (body_text.size() > 0) {
+      TSHttpTxnErrorBodySet(txnp_, TSstrndup(body_text.data(), body_text.size()), body_text.size(),
+                            nullptr); // Defaults to text/html
+    }
 
     local_reply_headers_ = additional_headers;
     local_reply_details_ = details;
diff --git a/plugins/experimental/wasm/ats_context.h b/plugins/experimental/wasm/ats_context.h
index 8230fb4b0..fcb65d070 100644
--- a/plugins/experimental/wasm/ats_context.h
+++ b/plugins/experimental/wasm/ats_context.h
@@ -57,54 +57,54 @@ using proxy_wasm::MetricType;
 class Wasm;
 
 // constants for property names
-constexpr std::string_view p_request_path                         = {"request\0path\0", 13};
-constexpr std::string_view p_request_url_path                     = {"request\0url_path\0", 17};
-constexpr std::string_view p_request_host                         = {"request\0host\0", 13};
-constexpr std::string_view p_request_scheme                       = {"request\0scheme\0", 15};
-constexpr std::string_view p_request_method                       = {"request\0method\0", 15};
-constexpr std::string_view p_request_headers                      = {"request\0headers\0", 16};
-constexpr std::string_view p_request_referer                      = {"request\0referer\0", 16};
-constexpr std::string_view p_request_useragent                    = {"request\0useragent\0", 18};
-constexpr std::string_view p_request_time                         = {"request\0time\0", 13};
-constexpr std::string_view p_request_id                           = {"request\0id\0", 11};
-constexpr std::string_view p_request_protocol                     = {"request\0protocol\0", 17};
-constexpr std::string_view p_request_query                        = {"request\0query\0", 14};
-constexpr std::string_view p_request_duration                     = {"request\0duration\0", 17};
-constexpr std::string_view p_request_size                         = {"request\0size\0", 13};
-constexpr std::string_view p_request_total_size                   = {"request\0total_size\0", 19};
-constexpr std::string_view p_response_code                        = {"response\0code\0", 14};
-constexpr std::string_view p_response_code_details                = {"response\0code_details\0", 22};
-constexpr std::string_view p_response_headers                     = {"response\0headers\0", 17};
-constexpr std::string_view p_response_size                        = {"response\0size\0", 14};
-constexpr std::string_view p_response_total_size                  = {"response\0total_size\0", 20};
+constexpr std::string_view p_request_path                         = {"request\0path", 12};
+constexpr std::string_view p_request_url_path                     = {"request\0url_path", 16};
+constexpr std::string_view p_request_host                         = {"request\0host", 12};
+constexpr std::string_view p_request_scheme                       = {"request\0scheme", 14};
+constexpr std::string_view p_request_method                       = {"request\0method", 14};
+constexpr std::string_view p_request_headers                      = {"request\0headers", 15};
+constexpr std::string_view p_request_referer                      = {"request\0referer", 15};
+constexpr std::string_view p_request_useragent                    = {"request\0useragent", 17};
+constexpr std::string_view p_request_time                         = {"request\0time", 12};
+constexpr std::string_view p_request_id                           = {"request\0id", 10};
+constexpr std::string_view p_request_protocol                     = {"request\0protocol", 16};
+constexpr std::string_view p_request_query                        = {"request\0query", 13};
+constexpr std::string_view p_request_duration                     = {"request\0duration", 16};
+constexpr std::string_view p_request_size                         = {"request\0size", 12};
+constexpr std::string_view p_request_total_size                   = {"request\0total_size", 18};
+constexpr std::string_view p_response_code                        = {"response\0code", 13};
+constexpr std::string_view p_response_code_details                = {"response\0code_details", 21};
+constexpr std::string_view p_response_headers                     = {"response\0headers", 16};
+constexpr std::string_view p_response_size                        = {"response\0size", 13};
+constexpr std::string_view p_response_total_size                  = {"response\0total_size", 19};
 constexpr std::string_view p_node                                 = {"node", 4};
 constexpr std::string_view p_plugin_name                          = {"plugin_name", 11};
 constexpr std::string_view p_plugin_root_id                       = {"plugin_root_id", 14};
 constexpr std::string_view p_plugin_vm_id                         = {"plugin_vm_id", 12};
-constexpr std::string_view p_source_address                       = {"source\0address\0", 15};
-constexpr std::string_view p_source_port                          = {"source\0port\0", 12};
-constexpr std::string_view p_destination_address                  = {"destination\0address\0", 20};
-constexpr std::string_view p_destination_port                     = {"destination\0port\0", 17};
-constexpr std::string_view p_connection_mtls                      = {"connection\0mtls\0", 16};
-constexpr std::string_view p_connection_requested_server_name     = {"connection\0requested_server_name\0", 33};
-constexpr std::string_view p_connection_tls_version               = {"connection\0tls_version\0", 23};
-constexpr std::string_view p_connection_subject_local_certificate = {"connection\0subject_local_certificate\0", 37};
-constexpr std::string_view p_connection_subject_peer_certificate  = {"connection\0subject_peer_certificate\0", 36};
-constexpr std::string_view p_connection_dns_san_local_certificate = {"connection\0dns_san_local_certificate\0", 37};
-constexpr std::string_view p_connection_dns_san_peer_certificate  = {"connection\0dns_san_peer_certificate\0", 36};
-constexpr std::string_view p_connection_uri_san_local_certificate = {"connection\0uri_san_local_certificate\0", 37};
-constexpr std::string_view p_connection_uri_san_peer_certificate  = {"connection\0uri_san_peer_certificate\0", 36};
-constexpr std::string_view p_upstream_address                     = {"upstream\0address\0", 17};
-constexpr std::string_view p_upstream_port                        = {"upstream\0port\0", 14};
-constexpr std::string_view p_upstream_local_address               = {"upstream\0local_address\0", 23};
-constexpr std::string_view p_upstream_local_port                  = {"upstream\0local_port\0", 20};
-constexpr std::string_view p_upstream_tls_version                 = {"upstream\0tls_version\0", 21};
-constexpr std::string_view p_upstream_subject_local_certificate   = {"upstream\0subject_local_certificate\0", 36};
-constexpr std::string_view p_upstream_subject_peer_certificate    = {"upstream\0subject_peer_certificate\0", 35};
-constexpr std::string_view p_upstream_dns_san_local_certificate   = {"upstream\0dns_san_local_certificate\0", 36};
-constexpr std::string_view p_upstream_dns_san_peer_certificate    = {"upstream\0dns_san_peer_certificate\0", 35};
-constexpr std::string_view p_upstream_uri_san_local_certificate   = {"upstream\0uri_san_local_certificate\0", 36};
-constexpr std::string_view p_upstream_uri_san_peer_certificate    = {"upstream\0uri_san_peer_certificate\0", 35};
+constexpr std::string_view p_source_address                       = {"source\0address", 14};
+constexpr std::string_view p_source_port                          = {"source\0port", 11};
+constexpr std::string_view p_destination_address                  = {"destination\0address", 19};
+constexpr std::string_view p_destination_port                     = {"destination\0port", 16};
+constexpr std::string_view p_connection_mtls                      = {"connection\0mtls", 15};
+constexpr std::string_view p_connection_requested_server_name     = {"connection\0requested_server_name", 32};
+constexpr std::string_view p_connection_tls_version               = {"connection\0tls_version", 22};
+constexpr std::string_view p_connection_subject_local_certificate = {"connection\0subject_local_certificate", 36};
+constexpr std::string_view p_connection_subject_peer_certificate  = {"connection\0subject_peer_certificate", 35};
+constexpr std::string_view p_connection_dns_san_local_certificate = {"connection\0dns_san_local_certificate", 36};
+constexpr std::string_view p_connection_dns_san_peer_certificate  = {"connection\0dns_san_peer_certificate", 35};
+constexpr std::string_view p_connection_uri_san_local_certificate = {"connection\0uri_san_local_certificate", 36};
+constexpr std::string_view p_connection_uri_san_peer_certificate  = {"connection\0uri_san_peer_certificate", 35};
+constexpr std::string_view p_upstream_address                     = {"upstream\0address", 16};
+constexpr std::string_view p_upstream_port                        = {"upstream\0port", 13};
+constexpr std::string_view p_upstream_local_address               = {"upstream\0local_address", 22};
+constexpr std::string_view p_upstream_local_port                  = {"upstream\0local_port", 19};
+constexpr std::string_view p_upstream_tls_version                 = {"upstream\0tls_version", 20};
+constexpr std::string_view p_upstream_subject_local_certificate   = {"upstream\0subject_local_certificate", 35};
+constexpr std::string_view p_upstream_subject_peer_certificate    = {"upstream\0subject_peer_certificate", 34};
+constexpr std::string_view p_upstream_dns_san_local_certificate   = {"upstream\0dns_san_local_certificate", 35};
+constexpr std::string_view p_upstream_dns_san_peer_certificate    = {"upstream\0dns_san_peer_certificate", 34};
+constexpr std::string_view p_upstream_uri_san_local_certificate   = {"upstream\0uri_san_local_certificate", 35};
+constexpr std::string_view p_upstream_uri_san_peer_certificate    = {"upstream\0uri_san_peer_certificate", 34};
 
 // constants for property values
 constexpr std::string_view pv_http2  = {"HTTP/2", 6};
@@ -119,9 +119,7 @@ struct HeaderMap {
 
   ~HeaderMap()
   {
-    TSDebug(WASM_DEBUG_TAG, "Releasing header map");
     if (bufp != nullptr) {
-      TSDebug(WASM_DEBUG_TAG, "Releasing bufp/hdr_loc");
       TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
     }
   }
@@ -168,6 +166,8 @@ public:
 
   uint64_t getCurrentTimeNanoseconds() override;
 
+  uint64_t getMonotonicTimeNanoseconds() override;
+
   std::string_view getConfiguration() override;
 
   WasmResult setTimerPeriod(std::chrono::milliseconds period, uint32_t *timer_token_ptr) override;
diff --git a/plugins/experimental/wasm/examples/tinygo/README.md b/plugins/experimental/wasm/examples/tinygo/README.md
new file mode 100755
index 000000000..a8f070e23
--- /dev/null
+++ b/plugins/experimental/wasm/examples/tinygo/README.md
@@ -0,0 +1,13 @@
+TinyGo example for ATS Wasm Plugin
+
+[Coraza Proxy WASM](https://github.com/corazawaf/coraza-proxy-wasm) is WAF wasm filter built on top of [Coraza](https://github.com/corazawaf/coraza) and implementing [proxy-wasm ABI](https://github.com/proxy-wasm/spec)
+
+To retrieve `plugin.wasm` for the Coraza Proxy WASM
+* `docker pull ghcr.io/corazawaf/coraza-proxy-wasm:main`
+* `docker container create ghcr.io/corazawaf/coraza-proxy-wasm:main '/plugin.wasm'`
+* `docker cp <container id>:/plugin.wasm /usr/local/var/wasm/plugin.wasm`
+
+Copy the yaml in this directory to `/usr/local/var/wasm/` and activate the plugin in `plugin.config`
+* `wasm.so /usr/local/var/wasm/plugin.yaml`
+
+After restarting ATS, any request with `perl` as the user agent will retreive a status 403 response.
diff --git a/plugins/experimental/wasm/examples/tinygo/plugin.yaml b/plugins/experimental/wasm/examples/tinygo/plugin.yaml
new file mode 100644
index 000000000..f4a5dd6de
--- /dev/null
+++ b/plugins/experimental/wasm/examples/tinygo/plugin.yaml
@@ -0,0 +1,18 @@
+config:
+  configuration: |
+      {
+        "rules": [
+          "SecDebugLogLevel 5",
+          "SecRuleEngine On",
+          "SecRule REQUEST_HEADERS:User-Agent \"perl\" \"id:1234,deny,status:403\""
+        ]
+      }
+  name: "coraza-filter"
+  rootId: "test"
+  vmConfig:
+    code:
+      local:
+        filename: /usr/local/var/wasm/plugin.wasm
+    runtime: envoy.wasm.runtime.wavm
+    vmId: "coraza-filter_vm_id"
+    allow_precompiled: true