Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ behavior_changes:
hardware thread count and CPU affinity for worker thread calculation. Uses conservative rounding (floor)
to account for non-worker threads and prevent container throttling, which may reduce the total number of
connections.
- area: dynamic modules
change: |
The dynamic module ABI has been updated to support streaming body manipulation. This change also
fixed potential incorrect behavior when access or modify the request or response body. See
https://github.com/envoyproxy/envoy/issues/40918 for more details.

minor_behavior_changes:
# *Changes that may cause incompatibilities for some users, but should not for most*
Expand Down
189 changes: 136 additions & 53 deletions source/extensions/dynamic_modules/abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1378,14 +1378,53 @@ void envoy_dynamic_module_callback_http_send_response_trailers(
// ------------------- HTTP Request/Response body callbacks --------------------

/**
* envoy_dynamic_module_callback_http_get_request_body_vector is called by the module to get the
* request body as a vector of buffers. The body is returned as an array of
* NOTE: Envoy will handle the request/response as a stream of data. Therefore, the body may not be
* available in its entirety before the end of stream flag is set. The Envoy will provides both the
* received body (body pieces received in the latest event) and the buffered body (body pieces
* buffered so far) to the module. The module should be aware of this distinction when processing
* the body.
*
* NOTE: The received body could only be available during the request/response body
* event hooks (the envoy_dynamic_module_on_http_filter_request_body and
* envoy_dynamic_module_on_http_filter_response_body).
* Outside of these hooks, the received body will be unavailable.
*
* NOTE: The buffered body, however, is always available. But only the latest data processing filter
* in the filter chain could modify the buffered body. That is say for a given filter X, filter X
* can safely modify the buffered body if and only if the filters following filter X in the filter
* chain have not yet accessed the body.
*/

/**
* envoy_dynamic_module_callback_http_get_received_request_body_vector is called by the module to
* get the current request body as a vector of buffers. The body is returned as an array of
* envoy_dynamic_module_type_envoy_buffer.
*
* PRECONDITION: The module must ensure that the result_buffer_vector is valid and has enough length
* to store all the buffers. The module can use
* envoy_dynamic_module_callback_http_get_received_request_body_vector_size to get the number of
* buffers before calling this function.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param result_buffer_vector is the pointer to the array of envoy_dynamic_module_type_envoy_buffer
* where the buffers of the body will be stored. The lifetime of the buffer is guaranteed until the
* end of the current event hook unless the setter callback is called.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_get_received_request_body_vector(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_envoy_buffer* result_buffer_vector);

/**
* envoy_dynamic_module_callback_http_get_buffered_request_body_vector is called by the module to
* get the buffered request body as a vector of buffers. The body is returned as an array of
* envoy_dynamic_module_type_envoy_buffer.
*
* PRECONDITION: The module must ensure that the result_buffer_vector is valid and has enough length
* to store all the buffers. The module can use
* envoy_dynamic_module_callback_http_get_request_body_vector_size to get the number of buffers
* before calling this function.
* envoy_dynamic_module_callback_http_get_buffered_request_body_vector_size to get the number of
* buffers before calling this function.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
Expand All @@ -1394,115 +1433,159 @@ void envoy_dynamic_module_callback_http_send_response_trailers(
* end of the current event hook unless the setter callback is called.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_get_request_body_vector(
bool envoy_dynamic_module_callback_http_get_buffered_request_body_vector(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_envoy_buffer* result_buffer_vector);

/**
* envoy_dynamic_module_callback_http_get_request_body_vector_size is called by the module to get
* the number of buffers in the request body. Combined with
* envoy_dynamic_module_callback_http_get_request_body_vector, this can be used to iterate over all
* buffers in the request body.
* envoy_dynamic_module_callback_http_get_received_request_body_vector_size is called by the module
* to get the number of buffers in the current request body. Combined with
* envoy_dynamic_module_callback_http_get_received_request_body_vector, this can be used to iterate
* over all buffers in the request body.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param size is the pointer to the variable where the number of buffers will be stored.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_get_request_body_vector_size(
bool envoy_dynamic_module_callback_http_get_received_request_body_vector_size(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t* size);

/**
* envoy_dynamic_module_callback_http_append_request_body is called by the module to append the
* given data to the end of the request body.
* envoy_dynamic_module_callback_http_get_buffered_request_body_vector_size is called by the module
* to get the number of buffers in the buffered request body. Combined with
* envoy_dynamic_module_callback_http_get_buffered_request_body_vector, this can be used to iterate
* over all buffers in the request body.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param size is the pointer to the variable where the number of buffers will be stored.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_get_buffered_request_body_vector_size(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t* size);

/**
* envoy_dynamic_module_callback_http_append_received_request_body is called by the module to append
* the given data to the end of the current request body.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param data is the pointer to the buffer of the data to be appended.
* @param length is the length of the data.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_append_request_body(
bool envoy_dynamic_module_callback_http_append_received_request_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_buffer_module_ptr data, size_t length);

/**
* envoy_dynamic_module_callback_http_drain_request_body is called by the module to drain the given
* number of bytes from the request body. If the number of bytes to drain is greater than
* the size of the body, the whole body will be drained.
* envoy_dynamic_module_callback_http_append_buffered_request_body is called by the module to append
* the given data to the end of the buffered request body.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param data is the pointer to the buffer of the data to be appended.
* @param length is the length of the data.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_append_buffered_request_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_buffer_module_ptr data, size_t length);

/**
* envoy_dynamic_module_callback_http_drain_received_request_body is called by the module to drain
* the given number of bytes from the current request body. If the number of bytes to drain is
* greater than the size of the body, the whole body will be drained.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param number_of_bytes is the number of bytes to drain.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_drain_request_body(
bool envoy_dynamic_module_callback_http_drain_received_request_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t number_of_bytes);

/**
* envoy_dynamic_module_callback_http_inject_request_body is called by the module to
* inject the given request data directly into the filter stream. This method should only be called
* from a scheduled event.
* envoy_dynamic_module_callback_http_drain_buffered_request_body is called by the module to drain
* the given number of bytes from the buffered request body. If the number of bytes to drain is
* greater than the size of the body, the whole body will be drained.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param data is the pointer to the buffer of the data to be injected.
* @param length is the length of the data.
* @param end_stream is true if this is the last data to be injected.
* @param number_of_bytes is the number of bytes to drain.
* @return true if the body is available, false otherwise.
*/
bool envoy_dynamic_module_callback_http_inject_request_body(
bool envoy_dynamic_module_callback_http_drain_buffered_request_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t number_of_bytes);

/**
* This is the same as envoy_dynamic_module_callback_http_get_received_request_body_vector, but for
* the current response body. See the comments on
* envoy_dynamic_module_callback_http_get_received_request_body_vector for more details.
*/
bool envoy_dynamic_module_callback_http_get_received_response_body_vector(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_buffer_module_ptr data, size_t length, bool end_stream);
envoy_dynamic_module_type_envoy_buffer* result_buffer_vector);

/**
* This is the same as envoy_dynamic_module_callback_http_get_request_body_vector, but for the
* response body. See the comments on envoy_dynamic_module_callback_http_get_request_body_vector
* for more details.
* This is the same as envoy_dynamic_module_callback_http_get_buffered_request_body_vector, but for
* the buffered response body. See the comments on
* envoy_dynamic_module_callback_http_get_buffered_request_body_vector for more details.
*/
bool envoy_dynamic_module_callback_http_get_response_body_vector(
bool envoy_dynamic_module_callback_http_get_buffered_response_body_vector(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_envoy_buffer* result_buffer_vector);

/**
* This is the same as envoy_dynamic_module_callback_http_get_request_body_vector_size, but for the
* response body. See the comments on
* envoy_dynamic_module_callback_http_get_request_body_vector_size for more details.
* This is the same as envoy_dynamic_module_callback_http_get_received_request_body_vector_size, but
* for the current response body. See the comments on
* envoy_dynamic_module_callback_http_get_received_request_body_vector_size for more details.
*/
bool envoy_dynamic_module_callback_http_get_response_body_vector_size(
bool envoy_dynamic_module_callback_http_get_received_response_body_vector_size(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t* size);

/**
* This is the same as envoy_dynamic_module_callback_http_append_request_body, but for the response
* body. See the comments on envoy_dynamic_module_callback_http_append_request_body for more
* details.
* This is the same as envoy_dynamic_module_callback_http_get_buffered_request_body_vector_size, but
* for the buffered response body. See the comments on
* envoy_dynamic_module_callback_http_get_buffered_request_body_vector_size for more details.
*/
bool envoy_dynamic_module_callback_http_append_response_body(
bool envoy_dynamic_module_callback_http_get_buffered_response_body_vector_size(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t* size);

/**
* This is the same as envoy_dynamic_module_callback_http_append_received_request_body, but for the
* current response body. See the comments on
* envoy_dynamic_module_callback_http_append_received_request_body for more details.
*/
bool envoy_dynamic_module_callback_http_append_received_response_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_buffer_module_ptr data, size_t length);

/**
* This is the same as envoy_dynamic_module_callback_http_append_buffered_request_body, but for the
* buffered response body. See the comments on
* envoy_dynamic_module_callback_http_append_buffered_request_body for more details.
*/
bool envoy_dynamic_module_callback_http_append_buffered_response_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_buffer_module_ptr data, size_t length);

/**
* This is the same as envoy_dynamic_module_callback_http_drain_request_body, but for the response
* body. See the comments on envoy_dynamic_module_callback_http_drain_request_body for more details.
* This is the same as envoy_dynamic_module_callback_http_drain_received_request_body, but for the
* current response body. See the comments on
* envoy_dynamic_module_callback_http_drain_received_request_body for more details.
*/
bool envoy_dynamic_module_callback_http_drain_response_body(
bool envoy_dynamic_module_callback_http_drain_received_response_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t number_of_bytes);

/**
* envoy_dynamic_module_callback_http_inject_response_body is called by the module to
* inject the given response data directly into the filter stream. This method should only be called
* from a scheduled event.
*
* @param filter_envoy_ptr is the pointer to the DynamicModuleHttpFilter object of the
* corresponding HTTP filter.
* @param data is the pointer to the buffer of the data to be injected.
* @param length is the length of the data.
* @param end_stream is true if this is the last data to be injected.
* @return true if the body is available, false otherwise.
* This is the same as envoy_dynamic_module_callback_http_drain_buffered_request_body, but for the
* buffered response body. See the comments on
* envoy_dynamic_module_callback_http_drain_buffered_request_body for more details.
*/
bool envoy_dynamic_module_callback_http_inject_response_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr,
envoy_dynamic_module_type_buffer_module_ptr data, size_t length, bool end_stream);
bool envoy_dynamic_module_callback_http_drain_buffered_response_body(
envoy_dynamic_module_type_http_filter_envoy_ptr filter_envoy_ptr, size_t number_of_bytes);

// ---------------------------- Metadata Callbacks -----------------------------

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 = "dcd3808436396000e681f7014dda187ca87708995367ea1374e4b3191281cb7c";
const char* kAbiVersion = "52972436b8fd594556e76e1f9adfe1c22b7fd4a6bd3bbe6d9cdc8e0d7903dc68";

#ifdef __cplusplus
} // namespace DynamicModules
Expand Down
Loading