robtfm
robtfm4w ago

intercept an op rust-side and call the original fn

Hi, i'm using deno_core and some exts embedded in a desktop application, and am trying to replace an existing op with my own version in which i do some additional checks before calling to the original op's function. i can replace the op using Extension::middleware_fn, but i can't see a way to access the original op's function. the simplest way i can think to do this would be to modify the op2 macro to expose the raw function. am i missing something simpler? for context, i want to modify op_ws_create from deno_websocket to do a (potentially asynchronous) permission check, and add some default headers. i don't want to do it javascript-side because i worry that would be exploitable, but maybe it can be done safely (my js knowledge is far below my rust knowledge). i can't use the built-in WebSocketPermissions trait as it is a synchronous function (i guess i could modify it to be async instead).
5 Replies
Deno AI Helper
I wasn't able to find the answer to your question in the official Deno documentation. However, based on your message, I can provide some general advice, but please note that this advice is not based on the Deno documentation, and you should double-check the accuracy of the advice given. From your description, it seems like you are trying to perform a sort of "aspect-oriented programming" by intercepting and wrapping an existing operation in deno_core. If the Extension::middleware_fn does not provide a way to call the original operation, one potential approach could be to store a reference to the original operation before you replace it with your own. Then, in your custom operation, you could invoke the original operation after performing your additional checks. Here's a very high-level and conceptual example of what this might look like in Rust:
let original_op = get_original_op("op_ws_create"); // Pseudocode: Replace with actual method to get the op.

let custom_op = move |state, control: &[u8], zero_copy: Option<ZeroCopyBuf>| {
// Perform your additional checks here.

// Then call the original operation.
original_op(state, control, zero_copy)
};

// Replace the original op with your custom op.
// Again, this is pseudocode and the actual method to replace the op may differ.
replace_op("op_ws_create", custom_op);
let original_op = get_original_op("op_ws_create"); // Pseudocode: Replace with actual method to get the op.

let custom_op = move |state, control: &[u8], zero_copy: Option<ZeroCopyBuf>| {
// Perform your additional checks here.

// Then call the original operation.
original_op(state, control, zero_copy)
};

// Replace the original op with your custom op.
// Again, this is pseudocode and the actual method to replace the op may differ.
replace_op("op_ws_create", custom_op);
Please note that the above code is not actual Rust code and will not work as-is. It's meant to illustrate the concept of wrapping and calling the original operation. You will need to adapt this concept to the actual APIs provided by deno_core and deno_websocket. Since modifying the op2 macro or the WebSocketPermissions trait involves changes to the Deno internals, it might be worth considering contributing these changes
Deno AI Helper
upstream if you believe they could be beneficial to others. However, this would require a good understanding of the Deno project's contribution guidelines and acceptance criteria. Remember to carefully test any changes you make to ensure that they do not introduce security vulnerabilities or other issues. If you're unsure about the best approach, you might want to discuss your use case with the Deno community or contributors who might have faced similar challenges.
Deno AI Helper
🦕 Oops! Can you pinpoint where I went wrong to help me improve? 📈
robtfm
robtfm4w ago
rm -rf *
Deno AI Helper
It seems like you're referencing a shell command that recursively and forcefully removes all files and directories in the current directory. However, in the context of Deno, if you want to remove files or directories, you would use the Deno API to do so. The Deno runtime provides APIs to remove files and directories, which can be used programmatically in your Deno scripts. Here's an example of how you can remove a directory and its contents using Deno's standard library:
// This example uses Deno's standard library to remove a directory recursively.
// Make sure to handle errors appropriately in your real-world code.

import { emptyDir } from "https://deno.land/std/fs/mod.ts";

// Specify the directory you want to remove
const directory = "./path/to/directory";

// Remove the directory and its contents
await emptyDir(directory);

// Now that the directory is empty, you can remove it
await Deno.remove(directory);
// This example uses Deno's standard library to remove a directory recursively.
// Make sure to handle errors appropriately in your real-world code.

import { emptyDir } from "https://deno.land/std/fs/mod.ts";

// Specify the directory you want to remove
const directory = "./path/to/directory";

// Remove the directory and its contents
await emptyDir(directory);

// Now that the directory is empty, you can remove it
await Deno.remove(directory);
Please note that using Deno.remove() with the recursive option set to true is a powerful operation that will delete everything in the specified directory without confirmation, similar to rm -rf * in a shell environment. Always use it with caution to avoid unintentional data loss. Also, keep in mind that to run a script that performs file system operations like removing files or directories, you need to grant the necessary permissions. For the above code, you would need to run your Deno script with the --allow-write flag to allow write access to the file system:
deno run --allow-write script.ts
deno run --allow-write script.ts
Replace script.ts with the path to your Deno script file. Always be cautious with granting permissions, especially write access, to ensure your system's security. 🦕