--- categories: - docs - develop - stack - oss - rs - rc - oss - kubernetes - clients description: Working with binary data linkTitle: Binary data title: Binary data weight: 8 aliases: - /develop/interact/programmability/triggers-and-functions/concepts/binary_data/ --- By default, triggers and functions will decode all data as a string and will raise error on failures. Though useful for most users, sometimes there is a need to work with binary data. In order to do so, the library developer has to consider the following: 1. Binary function arguments 2. Binary command results 3. Binary key names on [keyspace triggers]({{< relref "/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/Keyspace_Triggers" >}}) 4. Binary data on [stream triggers]({{< relref "/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/Stream_Triggers" >}}) ### Binary function arguments It is possible to instruct triggers and functions not to decode function arguments as `JS` `Strings` using the [redis.functionFlags.RAW_ARGUMENTS]({{< relref "/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/Function_Flags" >}}) function flag. In this case, the function arguments will be given as `JS` `ArrayBuffer`. Example: ```js #!js api_version=1.0 name=lib redis.registerFunction("my_set", (c, key, val) => { return c.call("set", key, val); }, { flags: [redis.functionFlags.RAW_ARGUMENTS] } ); ``` The above example will allow us to set `key` and `val` even if those are binary data. Run example: ```bash 127.0.0.1:6379> TFCALL lib.my_set 1 "\xaa" "\xaa" "OK" 127.0.0.1:6379> get "\xaa" "\xaa" ``` Notice that the `call` function also accepts `JS` `ArrayBuffer` arguments. ### Binary command results Getting function arguments as binary data is not enough. We might want to read binary data from a Redis key. In order to do this we can use the `callRaw` function, which will not decode the result as a `JS` `String` and instead will return the result as a `JS` `ArrayBuffer`. Example: ```js #!js api_version=1.0 name=lib redis.registerFunction("my_get", (c, key) => { return c.callRaw("get", key); }, { flags: [redis.functionFalgs.RAW_ARGUMENTS] } ); ``` The above example will be able to fetch binary data and return it to the user. For example: ```bash 27.0.0.1:6379> set "\xaa" "\xaa" OK 127.0.0.1:6379> TFCALL lib.my_get 1 "\xaa" "\xaa" ``` Notice that a `JS` `ArrayBuffer` can be returned by a function, it will be returned to the client as `bulk string`. ### Binary keys names on database triggers On [keyspace triggers]({{< relref "/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/Keyspace_Triggers" >}}), if the key name that triggered the event is binary, the `data.key` field will be NULL. The `data.key_raw` field is always provided as a `JS` `ArrayBuffer` and can be used as in the following example: ```js #!js api_version=1.0 name=lib /* The following is just an example, in general it is discourage to use globals. */ var n_notifications = 0; var last_key = null; var last_key_raw = null; redis.registerKeySpaceTrigger("consumer", "", function(client, data) { if (data.event == "set") { n_notifications += 1; last_data = data.key; last_key_raw = data.key_raw; } }); redis.registerFunction("notifications_stats", async function(){ return [ n_notifications, last_key, last_key_raw ]; }); ``` Run example: ```bash 127.0.0.1:6379> set "\xaa" "\xaa" OK 127.0.0.1:6379> TFCALL lib.notifications_stats 0 1) (integer) 1 2) (nil) 3) "\xaa" ``` For more information see [keyspace triggers]({{< relref "/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/Keyspace_Triggers" >}}). ### Binary data on stream consumers On [stream triggers]({{< relref "/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/Stream_Triggers" >}}), if the key name is binary. The `data.stream_name` field will be NULL. The `data.stream_name_raw` field is always provided as a `JS` `ArrayBuffer` and can be used in this case. In addition, if the content of the steam is binary, it will also appear as `null` under `data.record`. In this case, it is possible to use `data.record` (which always exists) and contains the data as a `JS` `ArrayBuffer`. Example: ```js #!js api_version=1.0 name=lib /* The following is just an example, in general it is discourage to use globals. */ var last_key = null; var last_key_raw = null; var last_data = null; var last_data_raw = null; redis.registerFunction("stats", function(){ return [ last_key, last_key_raw, last_data, last_data_raw ]; }) redis.registerStreamTrigger("consumer", new Uint8Array([255]).buffer, function(c, data){ last_key = data.stream_name; last_key_raw = data.stream_name_raw; last_data = data.record; last_data_raw = data.record_raw; }) ``` Run Example: ```bash 127.0.0.1:6379> xadd "\xff\xff" * "\xaa" "\xaa" "1659515146671-0" 127.0.0.1:6379> TFCALL foo.stats 0 1) (nil) 2) "\xff\xff" 3) 1) 1) (nil) 2) (nil) 4) 1) 1) "\xaa" 2) "\xaa" ```