Archived
115 lines
3.0 KiB
Rust
115 lines
3.0 KiB
Rust
//! Service binding implementations.
|
|
//!
|
|
//! Each binding protocol implements the `Binding` trait.
|
|
//! The proxy uses whatever binding is configured in `el.toml`.
|
|
|
|
pub mod direct;
|
|
pub mod grpc;
|
|
pub mod rest;
|
|
pub mod websocket;
|
|
|
|
use crate::ServiceResult;
|
|
use std::collections::HashMap;
|
|
|
|
/// Which protocol this service binding uses.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum BindingKind {
|
|
/// HTTP REST — maps service methods to HTTP endpoints.
|
|
Rest,
|
|
/// WebSocket — persistent connection, message-based RPC.
|
|
WebSocket,
|
|
/// gRPC — protobuf over HTTP/2 (stub; codegen is a future TODO).
|
|
Grpc,
|
|
/// Direct — server-side only; calls Rust functions directly, zero network.
|
|
Direct,
|
|
}
|
|
|
|
impl BindingKind {
|
|
pub fn from_str(s: &str) -> Option<Self> {
|
|
match s.to_lowercase().as_str() {
|
|
"rest" => Some(Self::Rest),
|
|
"websocket" | "ws" => Some(Self::WebSocket),
|
|
"grpc" => Some(Self::Grpc),
|
|
"direct" => Some(Self::Direct),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn as_str(&self) -> &'static str {
|
|
match self {
|
|
Self::Rest => "rest",
|
|
Self::WebSocket => "websocket",
|
|
Self::Grpc => "grpc",
|
|
Self::Direct => "direct",
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A service call request — method name and parameters.
|
|
#[derive(Debug, Clone)]
|
|
pub struct ServiceRequest {
|
|
pub service: String,
|
|
pub method: String,
|
|
/// Parameters as key-value pairs. Complex types are JSON-serialized strings.
|
|
pub params: HashMap<String, String>,
|
|
}
|
|
|
|
impl ServiceRequest {
|
|
pub fn new(service: impl Into<String>, method: impl Into<String>) -> Self {
|
|
Self {
|
|
service: service.into(),
|
|
method: method.into(),
|
|
params: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn with_param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
|
|
self.params.insert(key.into(), value.into());
|
|
self
|
|
}
|
|
}
|
|
|
|
/// A service call response — raw body string (JSON, protobuf bytes as hex, etc.)
|
|
#[derive(Debug, Clone)]
|
|
pub struct ServiceResponse {
|
|
pub status: u16,
|
|
pub body: String,
|
|
pub headers: HashMap<String, String>,
|
|
}
|
|
|
|
impl ServiceResponse {
|
|
pub fn ok(body: impl Into<String>) -> Self {
|
|
Self {
|
|
status: 200,
|
|
body: body.into(),
|
|
headers: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn error(status: u16, body: impl Into<String>) -> Self {
|
|
Self {
|
|
status,
|
|
body: body.into(),
|
|
headers: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn is_success(&self) -> bool {
|
|
(200..300).contains(&self.status)
|
|
}
|
|
}
|
|
|
|
/// The core binding trait — implemented by each protocol.
|
|
pub trait Binding: Send + Sync {
|
|
/// The kind of binding this is.
|
|
fn kind(&self) -> BindingKind;
|
|
|
|
/// Execute a service method call and return the response.
|
|
fn call(&self, request: ServiceRequest) -> ServiceResult<ServiceResponse>;
|
|
|
|
/// Whether this binding supports streaming responses.
|
|
fn supports_streaming(&self) -> bool {
|
|
false
|
|
}
|
|
}
|