Skip to content

Commit

Permalink
adds all getters API
Browse files Browse the repository at this point in the history
Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
  • Loading branch information
mathetake committed Dec 20, 2024
1 parent 2a44f22 commit 682a9cf
Show file tree
Hide file tree
Showing 8 changed files with 385 additions and 3 deletions.
8 changes: 8 additions & 0 deletions source/extensions/dynamic_modules/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,20 @@ envoy_cc_library(
# Note: with lld, we can use the glob matching to avoid listing all the symbols, but gold and ld are
# not able to do that. So we list all the symbols here.
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_request_header",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_request_headers",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_request_headers_count",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_set_request_header",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_request_trailer",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_request_trailers",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_request_trailers_count",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_set_request_trailer",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_response_header",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_response_headers",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_response_headers_count",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_set_response_header",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_response_trailer",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_response_trailers",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_get_response_trailers_count",
"-Wl,--export-dynamic-symbol=envoy_dynamic_module_callback_http_set_response_trailer",
],
deps = [
Expand Down
96 changes: 96 additions & 0 deletions source/extensions/dynamic_modules/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,17 @@ typedef char* envoy_dynamic_module_type_buffer_module_ptr;
*/
typedef char* envoy_dynamic_module_type_buffer_envoy_ptr;

/**
* envoy_dynamic_module_type_Header represents a key-value pair of an HTTP header. The key and value
* are represented as a pair of pointers to the buffer and the length of the buffer.
*/
typedef struct {
envoy_dynamic_module_type_buffer_module_ptr key_ptr;
size_t key_length;
envoy_dynamic_module_type_buffer_module_ptr value_ptr;
size_t value_length;
} envoy_dynamic_module_type_http_header;

/**
* envoy_dynamic_module_type_on_http_filter_request_headers_status represents the status of the
* filter after processing the HTTP request headers. This corresponds to `FilterHeadersStatus` in
Expand Down Expand Up @@ -454,6 +465,91 @@ size_t envoy_dynamic_module_callback_http_get_response_trailer(
envoy_dynamic_module_type_buffer_envoy_ptr* result_buffer_ptr, size_t* result_buffer_length_ptr,
size_t index);

/**
* envoy_dynamic_module_callback_http_get_request_headers_count is called by the module to get the
* number of request headers. Combined with envoy_dynamic_module_callback_http_get_request_headers,
* this can be used to iterate over all request headers.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @return the number of request headers. Returns zero if the headers are not available.
*/
size_t envoy_dynamic_module_callback_http_get_request_headers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr);

/**
* envoy_dynamic_module_callback_http_get_request_trailers_count is exactly the same as the
* envoy_dynamic_module_callback_http_get_request_headers_count, but for the request trailers.
* See the comments on envoy_dynamic_module_callback_http_get_request_headers_count for more
* details.
*/
size_t envoy_dynamic_module_callback_http_get_request_trailers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr);

/**
* envoy_dynamic_module_callback_http_get_response_headers_count is exactly the same as the
* envoy_dynamic_module_callback_http_get_request_headers_count, but for the response headers.
* See the comments on envoy_dynamic_module_callback_http_get_request_headers_count for more
* details.
*/
size_t envoy_dynamic_module_callback_http_get_response_headers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr);

/**
* envoy_dynamic_module_callback_http_get_response_trailers_count is exactly the same as the
* envoy_dynamic_module_callback_http_get_request_headers_count, but for the response trailers.
* See the comments on envoy_dynamic_module_callback_http_get_request_headers_count for more
* details.
*/
size_t envoy_dynamic_module_callback_http_get_response_trailers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr);

/**
* envoy_dynamic_module_callback_http_get_request_headers is called by the module to get all the
* request headers. The headers are returned as an array of envoy_dynamic_module_type_http_header.
*
* PRECONDITION: The module must ensure that the result_headers is valid and has enough length to
* store all the headers. The module can use
* envoy_dynamic_module_callback_http_get_request_headers_count to get the number of headers before
* calling this function.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param result_headers is the pointer to the array of envoy_dynamic_module_type_http_header where
* the headers will be stored.
* @return true if the operation is successful, false otherwise.
*/
bool envoy_dynamic_module_callback_http_get_request_headers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers);

/**
* envoy_dynamic_module_callback_http_get_request_trailers is exactly the same as the
* envoy_dynamic_module_callback_http_get_request_headers, but for the request trailers.
* See the comments on envoy_dynamic_module_callback_http_get_request_headers for more details.
*/
bool envoy_dynamic_module_callback_http_get_request_trailers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers);

/**
* envoy_dynamic_module_callback_http_get_response_headers is exactly the same as the
* envoy_dynamic_module_callback_http_get_request_headers, but for the response headers.
* See the comments on envoy_dynamic_module_callback_http_get_request_headers for more details.
*/
bool envoy_dynamic_module_callback_http_get_response_headers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers);

/**
* envoy_dynamic_module_callback_http_get_response_trailers is exactly the same as the
* envoy_dynamic_module_callback_http_get_request_headers, but for the response trailers.
* See the comments on envoy_dynamic_module_callback_http_get_request_headers for more details.
*/
bool envoy_dynamic_module_callback_http_get_response_trailers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers);

/**
* envoy_dynamic_module_callback_http_set_request_header is called by the module to set
* the value of the request header with the given key. If the header does not exist, it will be
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/dynamic_modules/abi_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace DynamicModules {
#endif
// This is the ABI version calculated as a sha256 hash of the ABI header files. When the ABI
// changes, this value must change, and the correctness of this value is checked by the test.
const char* kAbiVersion = "d6411c58dd9d3ed6ad3fb46ff64d004fac0e825a2cbf8497324b9ad56d160b43";
const char* kAbiVersion = "1377c40770c13c244cdf7d62f62535bb38979831288801d951259271bcc9884d";

#ifdef __cplusplus
} // namespace DynamicModules
Expand Down
70 changes: 70 additions & 0 deletions source/extensions/dynamic_modules/sdk/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,17 @@ impl EnvoyHttpFilter {
)
}

/// Get all request headers.
///
/// Returns a list of key-value pairs of the request headers.
/// If there are no headers or headers are not available, this returns an empty list.
pub fn get_request_headers(&self) -> Vec<(&[u8], &[u8])> {
self.get_headers_impl(
abi::envoy_dynamic_module_callback_http_get_request_headers_count,
abi::envoy_dynamic_module_callback_http_get_request_headers,
)
}

/// Set the request header with the given key and value.
///
/// This will overwrite the existing value if the header is already present.
Expand Down Expand Up @@ -281,6 +292,17 @@ impl EnvoyHttpFilter {
)
}

/// Get all request trailers.
///
/// Returns a list of key-value pairs of the request trailers.
/// If there are no trailers or trailers are not available, this returns an empty list.
pub fn get_request_trailers(&self) -> Vec<(&[u8], &[u8])> {
self.get_headers_impl(
abi::envoy_dynamic_module_callback_http_get_request_trailers_count,
abi::envoy_dynamic_module_callback_http_get_request_trailers,
)
}

/// Set the request trailer with the given key and value.
///
/// This will overwrite the existing value if the trailer is already present.
Expand Down Expand Up @@ -325,6 +347,17 @@ impl EnvoyHttpFilter {
)
}

/// Get all response headers.
///
/// Returns a list of key-value pairs of the response headers.
/// If there are no headers or headers are not available, this returns an empty list.
pub fn get_response_headers(&self) -> Vec<(&[u8], &[u8])> {
self.get_headers_impl(
abi::envoy_dynamic_module_callback_http_get_response_headers_count,
abi::envoy_dynamic_module_callback_http_get_response_headers,
)
}

/// Set the response header with the given key and value.
///
/// This will overwrite the existing value if the header is already present.
Expand Down Expand Up @@ -370,6 +403,17 @@ impl EnvoyHttpFilter {
)
}

/// Get all response trailers.
///
/// Returns a list of key-value pairs of the response trailers.
/// If there are no trailers or trailers are not available, this returns an empty list.
pub fn get_response_trailers(&self) -> Vec<(&[u8], &[u8])> {
self.get_headers_impl(
abi::envoy_dynamic_module_callback_http_get_response_trailers_count,
abi::envoy_dynamic_module_callback_http_get_response_trailers,
)
}

/// Set the response trailer with the given key and value.
///
/// This will overwrite the existing value if the trailer is already present.
Expand All @@ -393,6 +437,32 @@ impl EnvoyHttpFilter {
}
}

/// Implement the common logic for getting all headers/trailers.
fn get_headers_impl(
&self,
count_callback: unsafe extern "C" fn(
filter_envoy_ptr: abi::envoy_dynamic_module_type_http_filter_envoy_ptr,
) -> usize,
getter_callback: unsafe extern "C" fn(
filter_envoy_ptr: abi::envoy_dynamic_module_type_http_filter_envoy_ptr,
result_buffer_ptr: *mut abi::envoy_dynamic_module_type_http_header,
) -> bool,
) -> Vec<(&[u8], &[u8])> {
let count = unsafe { count_callback(self.raw_ptr) };
let mut headers = vec![(&[][..], &[][..]); count];
let success = unsafe {
getter_callback(
self.raw_ptr,
headers.as_mut_ptr() as *mut abi::envoy_dynamic_module_type_http_header,
)
};
if success {
headers
} else {
Vec::default()
}
}

/// This implements the common logic for getting the header/trailer values.
fn get_header_value_impl(
&self,
Expand Down
83 changes: 83 additions & 0 deletions source/extensions/filters/http/dynamic_modules/abi_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,89 @@ bool envoy_dynamic_module_callback_http_set_response_trailer(
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
return setHeaderValueImpl(filter->response_trailers_, key, key_length, value, value_length);
}

size_t envoy_dynamic_module_callback_http_get_request_headers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
if (!filter->request_headers_) {
return 0;
}
return filter->request_headers_->size();
}

size_t envoy_dynamic_module_callback_http_get_request_trailers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
if (!filter->request_trailers_) {
return 0;
}
return filter->request_trailers_->size();
}

size_t envoy_dynamic_module_callback_http_get_response_headers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
if (!filter->response_headers_) {
return 0;
}
return filter->response_headers_->size();
}

size_t envoy_dynamic_module_callback_http_get_response_trailers_count(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
if (!filter->response_trailers_) {
return 0;
}
return filter->response_trailers_->size();
}

bool getHeadersImpl(const Http::HeaderMap* map,
envoy_dynamic_module_type_http_header* result_headers) {
if (!map) {
return false;
}
size_t i = 0;
map->iterate([&i, &result_headers](const Http::HeaderEntry& header) -> Http::HeaderMap::Iterate {
auto& key = header.key();
result_headers[i].key_ptr = const_cast<char*>(key.getStringView().data());
result_headers[i].key_length = key.size();
auto& value = header.value();
result_headers[i].value_ptr = const_cast<char*>(value.getStringView().data());
result_headers[i].value_length = value.size();
i++;
return Http::HeaderMap::Iterate::Continue;
});
return true;
}

bool envoy_dynamic_module_callback_http_get_request_headers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
return getHeadersImpl(filter->request_headers_, result_headers);
}

bool envoy_dynamic_module_callback_http_get_request_trailers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
return getHeadersImpl(filter->request_trailers_, result_headers);
}

bool envoy_dynamic_module_callback_http_get_response_headers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
return getHeadersImpl(filter->response_headers_, result_headers);
}

bool envoy_dynamic_module_callback_http_get_response_trailers(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_http_header* result_headers) {
DynamicModuleHttpFilter* filter = static_cast<DynamicModuleHttpFilter*>(filter_envoy_ptr);
return getHeadersImpl(filter->response_trailers_, result_headers);
}
}
} // namespace HttpFilters
} // namespace DynamicModules
Expand Down
3 changes: 1 addition & 2 deletions source/extensions/filters/http/dynamic_modules/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ using namespace Envoy::Http;
class DynamicModuleHttpFilter : public Http::StreamFilter,
public std::enable_shared_from_this<DynamicModuleHttpFilter> {
public:
DynamicModuleHttpFilter(DynamicModuleHttpFilterConfigSharedPtr dynamic_module)
: config_(dynamic_module) {}
DynamicModuleHttpFilter(DynamicModuleHttpFilterConfigSharedPtr config) : config_(config) {}
~DynamicModuleHttpFilter() override = default;

/**
Expand Down
Loading

0 comments on commit 682a9cf

Please sign in to comment.