Skip to content

Conversation

@rekhoff
Copy link
Contributor

@rekhoff rekhoff commented Jan 1, 2026

Description of Changes

Rust added procedure-scoped HTTP via the procedure_http_request ABI (see Rust PR #3684) to C# host bindings.

What changed:

  1. Fix for BSATN wire format
  • Updated C# BSATN wire types for HTTP (BSATN.Runtime/HttpWireTypes.cs) to match exactly the Rust stable types:
    • spacetimedb_lib::http::Request fields and order: method, headers, timeout, uri, version
    • spacetimedb_lib::http::Response fields and order: headers, version, code
    • Header pairs are (name: string, value: bytes); no additional metadata is encoded.
  • Added explicit “do not reorder/extend” note in the C# wire type file since the host BSATN-decodes these bytes directly and may trap on mismatch.
  1. C# runtime HTTP client implementation
  • Implemented ProcedureContext.Http support (Runtime/Http.cs) that:
    • BSATN-serializes HttpRequestWire + sends body bytes via procedure_http_request
    • On success, BSATN-decodes HttpResponseWire and returns (response, body) as a typed HttpResponse
    • On HTTP_ERROR, decodes the error payload as a BSATN string
    • On WOULD_BLOCK_TRANSACTION, returns a stable error message (host rejects blocking HTTP while a mut tx is open)
    • Clamps timeouts to 500ms max (matching host behavior documented on the Rust side)
  1. ABI wiring / import plumbing
  • Added the procedure_http_request import to the C# wasm shim (Runtime/bindings.c) under the spacetime_10.3 import module.
  • Verified the generated C# P/Invoke signature matches the host ABI (request ptr/len, body ptr/len, out [BytesSource; 2]).
  1. Procedure entrypoint contract (trap vs errno)
  • Updated/clarified the module procedure trampoline behavior (Runtime/Internal/Module.call_procedure): it must either return Errno.OK or trap (log + rethrow). This mirrors the host’s expectations and avoids “unexpected errno values from guest entrypoints” behavior.
    Behavioral notes vs Rust
  • Rust bindings may expect(...)/panic on “should never happen” serialization failures; C# runtime explicitly avoids throwing across the procedure boundary for the HTTP client path and instead returns Result.Err for unexpected failures. This prevents whole-module traps from user-space HTTP usage while still surfacing rich errors.
  • The host remains authoritative on timeout enforcement; C# now mirrors the effective host clamp (500ms) to keep behavior aligned.

API and ABI breaking changes

No new host ABI introduced, and does not change the syscall signature.

  • This is not an ABI “break” in the host, but it is a guest-side wire compatibility correction: older C# guests built with the incorrect wire types could cause the host to trap during BSATN decode. After this PR, C# guests are compatible with the host’s expected layout.

Adds API: ProcedureContextBase.Http is available for procedures
No existing public types/method signatures are removed

  • A notable difference from Rust's panic behavior is that Rust code sometimes expect(...)s and may panic/trap on internal “should not happen” cases. On the other hand, C#'s HttpClient.Send explicitly converts unexpected failures into Result.Err to avoid trapping the module. This is a behavioral difference, but not an API break.

Expected complexity level and risk

2 - Mostly just creating equivalents to the Rust version.

Testing

C# regression tests updated to cover:

  • Successful request path (ReadMySchemaViaHttp)
  • Invalid request path (InvalidHttpRequest) returning error without trapping

Testing performed:

  • Full regression suite run against local node (see chat log); no wasm traps, all suites reported Success.

@rekhoff rekhoff self-assigned this Jan 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants