Use a single WASM HTTP request import

This commit is contained in:
pancake committed 2026-10-18 18:52:08 +02:00
1 parent 993de25e63
commit e1c3f02c72
4 files changed
+14 -13

No files matched your search

+3
View File
@@ -128,6 +128,9 @@ interactive terminal. Use `quit()`/`close()` or a context manager to release it.
Only HTTP(S) GET and POST are exposed, through radare2's existing
`r_socket_http_get()` and `r_socket_http_post()` C APIs. There are no socket
handles, listeners, UDP, WebSockets, or shell-curl execution.
The host ABI is one `r2.http_request(post, url, headers, data, code, length)`
import, with `post=0` for GET and `post=1` for POST. Update the host and WASM
module together; this replaces the earlier two-import bridge.
```sh
# In a clean radare2 checkout containing the HTTP bridge:
+2 -2
View File
@@ -37,12 +37,12 @@ class R2Pipe:
self._http = HttpBridge(self)
# Only the existing HTTP ABI is allowed in addition to Preview1.
for imported in module.imports:
if imported.module == "r2" and imported.name in ("http_get", "http_post"):
if imported.module == "r2" and imported.name == "http_request":
continue
if imported.module != "wasi_snapshot_preview1":
raise ValueError(f"Unsupported WASM import {imported.module}.{imported.name}; "
"use a wasi-api build")
if network and not any(item.module == "r2" and item.name == "http_get" for item in module.imports):
if network and not any(item.module == "r2" and item.name == "http_request" for item in module.imports):
raise ValueError("This WASM build has no HTTP bridge; use a wasi-api-http build")
required = {"memory", "malloc", "free", "r_core_new", "r_core_free",
"r_core_cmd_str", "r_core_file_open", "r_core_bin_load"}
+2 -7
View File
@@ -22,7 +22,8 @@ class HttpBridge:
def __init__(self, pipe):
self.pipe = pipe
def _request(self, method, url, headers, data, code, length):
def http_request(self, post, url, headers, data, code, length):
method = "POST" if post else "GET"
exports = self.pipe._exports
pointer = 0
try:
@@ -66,9 +67,3 @@ class HttpBridge:
if pointer:
exports.free(pointer)
return 0
def http_get(self, url, headers, code, length):
return self._request("GET", url, headers, 0, code, length)
def http_post(self, url, headers, data, code, length):
return self._request("POST", url, headers, data, code, length)
+7 -4
View File
@@ -65,10 +65,14 @@ class HttpServerTest(unittest.TestCase):
status, length = alloc(' '), alloc(' ')
result = 0
try:
fn = getattr(e, ('r_socket_http_' if is_real else 'http_') + method)
fn = getattr(e, 'r_socket_http_' + method) if is_real else e.http_request
args = [address, fields if headers else 0]
if not is_real:
args.insert(0, int(method == 'post'))
if method == 'post':
args.append(alloc('{"prompt":"hello món"}'))
elif not is_real:
args.append(0)
result = fn(*args, status, length) & 0xffffffff
if not result:
return None
@@ -89,9 +93,8 @@ class HttpServerTest(unittest.TestCase):
class HttpImportsTest(HttpServerTest):
def test_imports_opt_in_get_post_status_and_binary(self):
wat = '''(module
(import "r2" "http_get" (func $get (param i32 i32 i32 i32) (result i32)))
(import "r2" "http_post" (func $post (param i32 i32 i32 i32 i32) (result i32)))
(export "http_get" (func $get)) (export "http_post" (func $post))
(import "r2" "http_request" (func $request (param i32 i32 i32 i32 i32 i32) (result i32)))
(export "http_request" (func $request))
(memory (export "memory") 1)
(global $heap (mut i32) (i32.const 4096))
(func (export "malloc") (param $n i32) (result i32)