diff --git a/abi-versions/vNEXT/README.md b/abi-versions/vNEXT/README.md index 59748bb..2425869 100644 --- a/abi-versions/vNEXT/README.md +++ b/abi-versions/vNEXT/README.md @@ -528,6 +528,7 @@ in this section is restricted to specific callbacks: - `PLUGIN_CONFIGURATION` can be read in [`proxy_on_configure`]. - `FOREIGN_FUNCTION_ARGUMENTS` can be read in [`proxy_on_foreign_function`]. +- `UPSTREAM_CONFIGURATION` can be read in [`proxy_on_configure`]. ### Functions exposed by the host @@ -631,6 +632,8 @@ functions in this section is restricted to specific callbacks: [`proxy_on_http_call_response`]. - `HTTP_CALL_RESPONSE_TRAILERS` can be read in [`proxy_on_http_call_response`]. +- `HTTP_UPSTREAM_RESPONSE_HEADERS` can be read in + [`proxy_on_next_upstream`]. ### Functions exposed by the host @@ -1138,6 +1141,81 @@ Plugin must return one of the following values: - `PAUSE` to pause processing. +#### Upstream callbacks + +The host may expose upstream servers configuration to the plugin using +[`proxy_get_buffer_bytes`] with `buffer_id` set to `UPSTREAM_CONFIGURATION`, +which can be retrieved during [`proxy_on_configure`]. + +> **Note** +> The serialization format of the `UPSTREAM_CONFIGURATION` buffer is +> host-defined, as different proxies support different server parameters. + + +The following callbacks are invoked during upstream processing: + + +#### `proxy_on_upstream_select` + +* params: + - `i32 (uint32_t) stream_context_id` +* returns: + - none + +Called when the host is choosing an upstream for the HTTP request. + +During the callback `proxy_set_upstream` can be invoked to select an +upstream. If no upstream is selected, the host will select an upstream. + +Can be called multiple times depending on whether the selected upstream +could be reached, if it responded with a valid response and how many +attempts are allowed. + +Forwarding to another upstream can be aborted by calling `proxy_send_local_response`. + + +#### `proxy_on_next_upstream` + +* params: + - `i32 (uint32_t) stream_context_id` + - `i32 (uint32_t) status_code` +* returns: + - none + +The host may invoke this callback when upstream responds with a special HTTP status +code (status >= 300). + +`status_code` is the HTTP status code of the upstream response. + +All upstream response headers can be retrieved using +[`proxy_get_header_map_pairs`] with `map_id` set to `HTTP_UPSTREAM_RESPONSE_HEADERS`. + +Individual upstream response headers can be retrieved using +[`proxy_get_header_map_value`] with `map_id` set to `HTTP_UPSTREAM_RESPONSE_HEADERS`. + +During this callback `proxy_accept_upstream_response` can be called to accept the +current response and forward it downstream. + + +#### `proxy_on_upstream_info` + +* params: + - `i32 (uint32_t) stream_context_id` + - `i32 (`[`proxy_last_upstream_state`]`) last_state` +* returns: + - none + +Called each time the host finishes an attempt to get a response +from an upstream. + +Serves for retrieving information about the last upstream attempt. +Information can be retrieved by getting the `upstream.*` properties. + +The general state of the last attempt is provided by the `last_state` +- `FAILED` - upstream could not be contacted or sent an invalid response +- `OK` - upstream sent a valid response + + ### Functions exposed by the host #### `proxy_send_local_response` @@ -1168,6 +1246,102 @@ Returned `status` value is: point to invalid memory address. +#### `proxy_set_upstream` + +* params: + - `i32 (const char *) address_data` + - `i32 (size_t) address_size` + - `i32 (uint32_t) port` + - `i32 (uint32_t) tls` + - `i32 (const char *) sni_data` + - `i32 (size_t) sni_size` +* returns: + - `i32 (`[`proxy_status_t`]`) status` + +Sets the upstream peer address for the current HTTP request. + +`address_data` must be a valid IPv4 or IPv6 address in text form +(e.g. `192.168.1.1` or `::1`). + +`tls` selects the transport used for the upstream connection: +- `0` — plain TCP (`http://`). +- `1` — TLS (`https://`). + +`sni_data` and `sni_size` describe the optional TLS Server Name +Indication value sent during the TLS handshake. If `sni_size` is `0`, +no plugin-provided SNI is set and the host's default SNI resolution +applies. The SNI has no effect when `tls` is `0`. + +This can be used only in `proxy_on_upstream_select`. + +Returned `status` value is: +- `OK` on success. +- `BAD_ARGUMENT` when `address_data` is not a valid IP address, `port` + greater than `65535`, `tls` is not `0` or `1`, or an upstream was + already set for this invocation of `proxy_on_upstream_select`. +- `INVALID_MEMORY_ACCESS` when `address_data`, `address_size`, + `sni_data` or `sni_size` point to invalid memory address. + + +#### `proxy_accept_upstream_response` + +* params: +- none +* returns: + - `i32 (`[`proxy_status_t`]`) status` + +Accepts the last received upstream response and forwards it downstream. + +This can be used only in `proxy_on_next_upstream`. + +Returned `status` value is: +- `OK` on success. + + +#### `proxy_get_upstream_timeouts` + +* params: + - `i32 (uint32_t *) return_connect_timeout` + - `i32 (uint32_t *) return_send_timeout` + - `i32 (uint32_t *) return_read_timeout` +* returns: + - `i32 (`[`proxy_status_t`]`) status` + +Retrieves currently set timeouts: +- timeout for connecting to the upstream server (`return_connect_timeout`) +- timeout for sending the request to the upstream server, between +successive write operations (`return_send_timeout`) +- timeout for reading the response from the upstream server, between +successive read operations (`return_read_timeout`) + +This can be used only in `proxy_on_upstream_select`, +`proxy_on_next_upstream` or `proxy_on_upstream_info`. + +Returned `status` value is: +- `OK` on success. +- `INVALID_MEMORY_ACCESS` when `return_connect_timeout`, + `return_send_timeout` or `return_read_timeout` + point to invalid memory address. + + +#### `proxy_set_upstream_timeouts` + +* params: +- `i32 (uint32_t) connect_timeout` +- `i32 (uint32_t) send_timeout` +- `i32 (uint32_t) read_timeout` +* returns: + - `i32 (`[`proxy_status_t`]`) status` + +Sets timeouts for upstream proxying for the current HTTP request. +To skip setting a certain timeout, value 0 is used. + +This can be used only in `proxy_on_upstream_select`. + +Returned `status` value is: +- `OK` on success. + + ## HTTP calls ### Functions exposed by the host @@ -1788,8 +1962,14 @@ Returned `status` value is: #### Upstream connection properties -* `upstream.address` (string) - remote address -* `upstream.port` (int) - remote port +* `upstream.address` (string) - remote address and port +* `upstream.status` (int) - status code of the last upstream response +* `upstream.connect_time` (uint) - time to establish a connection to the + upstream server in milliseconds +* `upstream.response_time` (uint) - time to receive a full response from + the upstream server in milliseconds +* `upstream.header_time` (uint) - time to receive response headers from + the upstream server in milliseconds * `upstream.local_address` (string) - local address * `upstream.local_port` (int) - local port * `upstream.tls_version` (string) - TLS version @@ -2040,6 +2220,7 @@ changes to unrelated connections/requests. - `VM_CONFIGURATION` = `6` - `PLUGIN_CONFIGURATION` = `7` - `FOREIGN_FUNCTION_ARGUMENTS` = `8` +- `UPSTREAM_CONFIGURATION` = `9` #### `proxy_map_type_t` @@ -2052,6 +2233,7 @@ changes to unrelated connections/requests. - `GRPC_CALL_TRAILING_METADATA` = `5` - `HTTP_CALL_RESPONSE_HEADERS` = `6` - `HTTP_CALL_RESPONSE_TRAILERS` = `7` +- `HTTP_UPSTREAM_RESPONSE_HEADERS` = `8` #### `proxy_peer_type_t` @@ -2076,6 +2258,12 @@ changes to unrelated connections/requests. - `HISTOGRAM` = `2` +#### `proxy_last_upstream_state_t` + +- `OK` = `0` +- `FAILED` = `1` + + #### `wasi_errno_t` - `SUCCESS` = `0` @@ -2171,6 +2359,9 @@ changes to unrelated connections/requests. [`proxy_set_property`]: #proxy_set_property [`proxy_call_foreign_function`]: #proxy_call_foreign_function [`proxy_on_foreign_function`]: #proxy_on_foreign_function +[`proxy_on_upstream_select`]: #proxy_on_upstream_select +[`proxy_on_next_upstream`]: #proxy_on_next_upstream +[`proxy_on_upstream_info`]: #proxy_on_upstream_info [`wasi_snapshot_preview1.fd_write`]: #wasi_snapshot_preview1.fd_write [`wasi_snapshot_preview1.clock_time_get`]: #wasi_snapshot_preview1.clock_time_get @@ -2189,6 +2380,7 @@ changes to unrelated connections/requests. [`proxy_peer_type_t`]: #proxy_peer_type_t [`proxy_stream_type_t`]: #proxy_stream_type_t [`proxy_metric_type_t`]: #proxy_metric_type_t +[`proxy_last_upstream_state_t`]: #proxy_last_upstream_state [`wasi_errno_t`]: #wasi_errno_t [`wasi_fd_id_t`]: #wasi_fd_id_t