Overview
Extract and enhance backend functionality as a public API for both high-level and low-level use cases.
Current State:
- ✅ Basic backend resolution in
fastly_compute.requests.backend (internal)
- ✅ Static backend lookup via
wit_backend.Backend.open()
- ✅ Dynamic backend registration with TLS/timeout config
- ❌ Limited to requests facade - not exposed publicly
- ❌ Missing advanced features (client certs, custom CA, cipher selection, gRPC, pooling, keepalive)
- ❌ Returns raw WIT objects instead of wrapped resources
This Issue:
Create public fastly_compute.backend module exposing:
- Backend wrapper - Pythonic wrapper around WIT
Backend resource
- Advanced configuration - All WIT features (certs, ciphers, TLS versions, keepalive, pooling)
- Introspection API - Query backend properties (health, timeouts, TLS settings)
- Requests integration - Existing facade continues working unchanged
WIT Interface
interface backend {
use types.{error, open-error};
use http-types.{tls-version};
use secret-store.{secret};
resource dynamic-backend-options {
constructor();
override-host: func(value: string);
connect-timeout: func(value: u32);
first-byte-timeout: func(value: u32);
between-bytes-timeout: func(value: u32);
use-tls: func(value: bool);
tls-min-version: func(value: tls-version);
tls-max-version: func(value: tls-version);
cert-hostname: func(value: string);
ca-certificate: func(value: string);
tls-ciphers: func(value: string);
sni-hostname: func(value: string);
client-cert: func(client-cert: string, key: borrow<secret>);
http-keepalive-time-ms: func(value: u32);
tcp-keepalive-enable: func(value: u32);
tcp-keepalive-interval-secs: func(value: u32);
tcp-keepalive-probes: func(value: u32);
tcp-keepalive-time-secs: func(value: u32);
max-connections: func(value: u32);
max-use: func(value: u32);
max-lifetime-ms: func(value: u32);
pooling: func(value: bool);
grpc: func(value: bool);
prefer-ipv6: func(value: bool);
}
type timeout-ms = u32;
type timeout-secs = u32;
type probe-count = u32;
enum backend-health {
unknown,
healthy,
unhealthy,
}
resource backend {
open: static func(name: string) -> result<backend, open-error>;
get-name: func() -> string;
is-healthy: func() -> result<backend-health, error>;
is-dynamic: func() -> result<bool, error>;
get-host: func(max-len: u64) -> result<string, error>;
get-override-host: func(max-len: u64) -> result<option<list<u8>>, error>;
get-port: func() -> result<u16, error>;
get-connect-timeout-ms: func() -> result<timeout-ms, error>;
get-first-byte-timeout-ms: func() -> result<timeout-ms, error>;
get-between-bytes-timeout-ms: func() -> result<timeout-ms, error>;
is-tls: func() -> result<bool, error>;
get-tls-min-version: func() -> result<option<tls-version>, error>;
get-tls-max-version: func() -> result<option<tls-version>, error>;
get-http-keepalive-time: func() -> result<timeout-ms, error>;
get-tcp-keepalive-enable: func() -> result<bool, error>;
get-tcp-keepalive-interval: func() -> result<timeout-secs, error>;
get-tcp-keepalive-probes: func() -> result<probe-count, error>;
get-tcp-keepalive-time: func() -> result<timeout-secs, error>;
}
register-dynamic-backend: func(prefix: string, target: string, options: dynamic-backend-options) -> result<backend, error>;
}
WIT bindings: stubs/wit_world/imports/backend.py
API Design
Extract backend logic from internal fastly_compute.requests.backend module into public fastly_compute.backend:
- Implement
Backend resource wrapper around WIT Backend
- Static backends:
Backend.open(name)
- Dynamic backends:
Backend.create_dynamic(target, **options) for simple cases
- Advanced config:
Backend.register_dynamic(name, DynamicBackendConfig(...)) with dataclass for all WIT options (TLS, certs, timeouts, pooling, keepalive, gRPC)
- Introspection properties:
name, health, is_dynamic, host, port, connect_timeout (as timedelta), TLS settings
- Use
TLSVersion enum (V1_0, V1_1, V1_2, V1_3) and BackendHealth enum (UNKNOWN, HEALTHY, UNHEALTHY)
- Existing requests facade continues working unchanged (uses new module internally)
Cross-SDK Comparison: Rust uses builder pattern for dynamic backends, Go uses simple factory functions with struct fields, JS uses constructor config object. Python should use DynamicBackendConfig dataclass (more Pythonic than builder).
Viceroy Testing
Viceroy supports backend configuration via viceroy.toml and dynamic backend registration. Tests can verify SDK wrapper logic (property conversion, enum mapping, error handling), but actual backend requests require mock server or real endpoints.
Reference
Overview
Extract and enhance backend functionality as a public API for both high-level and low-level use cases.
Current State:
fastly_compute.requests.backend(internal)wit_backend.Backend.open()This Issue:
Create public
fastly_compute.backendmodule exposing:BackendresourceWIT Interface
WIT bindings:
stubs/wit_world/imports/backend.pyAPI Design
Extract backend logic from internal
fastly_compute.requests.backendmodule into publicfastly_compute.backend:Backendresource wrapper around WITBackendBackend.open(name)Backend.create_dynamic(target, **options)for simple casesBackend.register_dynamic(name, DynamicBackendConfig(...))with dataclass for all WIT options (TLS, certs, timeouts, pooling, keepalive, gRPC)name,health,is_dynamic,host,port,connect_timeout(astimedelta), TLS settingsTLSVersionenum (V1_0, V1_1, V1_2, V1_3) andBackendHealthenum (UNKNOWN, HEALTHY, UNHEALTHY)Cross-SDK Comparison: Rust uses builder pattern for dynamic backends, Go uses simple factory functions with struct fields, JS uses constructor config object. Python should use
DynamicBackendConfigdataclass (more Pythonic than builder).Viceroy Testing
Viceroy supports backend configuration via
viceroy.tomland dynamic backend registration. Tests can verify SDK wrapper logic (property conversion, enum mapping, error handling), but actual backend requests require mock server or real endpoints.Reference