chore: vendor sglang v0.5.10 snapshot

This commit is contained in:
2026-04-24 12:29:36 +00:00
parent 78f0d15221
commit bded08301f
4308 changed files with 1200894 additions and 2 deletions

View File

@@ -0,0 +1,10 @@
[package]
name = "wasm-guest-ratelimit"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wit-bindgen = { version = "0.21", features = ["macros"] }

View File

@@ -0,0 +1,68 @@
# WASM Rate Limit Example for sgl-model-gateway
This example demonstrates rate limiting middleware for sgl-model-gateway using the WebAssembly Component Model.
## Overview
This middleware provides rate limiting:
- **Default**: 60 requests per minute per identifier
- **Identifier Priority**: API Key > IP Address > Request ID
- **Response**: Returns `429 Too Many Requests` when limit exceeded
**Important**: This is a simplified demonstration. Since WASM components are stateless, each worker thread maintains its own counter. For production, implement rate limiting at the router/host level with shared state.
## Quick Start
### Build and Deploy
```bash
# Build
cd examples/wasm-guest-ratelimit
./build.sh
# Deploy (replace file_path with actual path)
curl -X POST http://localhost:3000/wasm \
-H "Content-Type: application/json" \
-d '{
"modules": [{
"name": "ratelimit-middleware",
"file_path": "/absolute/path/to/wasm_guest_ratelimit.component.wasm",
"module_type": "Middleware",
"attach_points": [{"Middleware": "OnRequest"}]
}]
}'
```
### Customization
Modify constants in `src/lib.rs`:
```rust
const RATE_LIMIT_REQUESTS: u64 = 100; // requests per window
const RATE_LIMIT_WINDOW_MS: u64 = 60_000; // time window in ms
```
## Testing
```bash
# Send multiple requests (first 60 succeed, then 429)
for i in {1..65}; do
curl -s -o /dev/null -w "%{http_code}\n" \
http://localhost:3000/v1/models \
-H "Authorization: Bearer secret-api-key-12345"
done
```
## Limitations
- Per-instance state (not shared across workers)
- No cross-process state sharing
- Memory growth with unique identifiers
- State lost on instance restart
## Troubleshooting
- Verify module attached to `OnRequest` phase
- Check identifier extraction logic matches request format
- Note: Each WASM worker has separate counter

View File

@@ -0,0 +1,77 @@
#!/bin/bash
# Build script for WASM guest rate limit example
# This script simplifies the build process for the WASM middleware component
set -e
echo "Building WASM guest rate limit example..."
# Check if we're in the right directory
if [ ! -f "Cargo.toml" ]; then
echo "Error: Cargo.toml not found. Please run this script from the wasm-guest-ratelimit directory."
exit 1
fi
# Check for required tools
command -v cargo >/dev/null 2>&1 || { echo "Error: cargo is required but not installed. Aborting." >&2; exit 1; }
# Check and install wasm32-wasip2 target
echo "Checking for wasm32-wasip2 target..."
if ! rustup target list --installed | grep -q "wasm32-wasip2"; then
echo "wasm32-wasip2 target not found. Installing..."
rustup target add wasm32-wasip2
echo "✓ wasm32-wasip2 target installed"
else
echo "✓ wasm32-wasip2 target already installed"
fi
# Check for wasm-tools
if ! command -v wasm-tools >/dev/null 2>&1; then
echo "Error: wasm-tools is required but not installed."
echo "Install it with: cargo install wasm-tools"
exit 1
fi
# Build with cargo (wit-bindgen uses cargo, not wasm-pack)
echo "Running cargo build..."
cargo build --target wasm32-wasip2 --release
# Output locations
WASM_MODULE="target/wasm32-wasip2/release/wasm_guest_ratelimit.wasm"
WASM_COMPONENT="target/wasm32-wasip2/release/wasm_guest_ratelimit.component.wasm"
if [ ! -f "$WASM_MODULE" ]; then
echo "Error: Build failed - WASM module not found"
exit 1
fi
# Check if the file is already a component
echo "Checking WASM file format..."
if wasm-tools print "$WASM_MODULE" 2>/dev/null | grep -q "^(\s*component"; then
echo "✓ WASM file is already in component format"
# Copy to component path for consistency
cp "$WASM_MODULE" "$WASM_COMPONENT"
else
# Wrap the WASM module into a component format
echo "Wrapping WASM module into component format..."
wasm-tools component new "$WASM_MODULE" -o "$WASM_COMPONENT"
if [ ! -f "$WASM_COMPONENT" ]; then
echo "Error: Failed to create component file"
exit 1
fi
fi
if [ -f "$WASM_COMPONENT" ]; then
echo ""
echo "✓ Build successful!"
echo " WASM module: $WASM_MODULE"
echo " WASM component: $WASM_COMPONENT"
echo ""
echo "Next steps:"
echo "1. Use the component file ($WASM_COMPONENT) when adding the module"
echo "2. Prepare the module configuration (see README.md for JSON format)"
echo "3. Use the API endpoint to add the module (see README.md for details)"
else
echo "Error: Component file not found"
exit 1
fi

View File

@@ -0,0 +1,155 @@
//! WASM Guest Rate Limit Example for sgl-model-gateway
//!
//! This example demonstrates rate limiting middleware
//! for sgl-model-gateway using the WebAssembly Component Model.
//!
//! Features:
//! - Rate limiting based on API Key or IP address
//! - Fixed time window (e.g., 60 requests per minute)
//! - Returns 429 Too Many Requests when limit exceeded
//!
//! Note: This is a simplified implementation. Since WASM components are stateless,
//! each instance maintains its own counters. For production use, consider
//! implementing rate limiting at the host/router level with shared state.
wit_bindgen::generate!({
path: "../../../src/wasm/interface",
world: "sgl-model-gateway",
});
use std::cell::RefCell;
use exports::sgl::model_gateway::{
middleware_on_request::Guest as OnRequestGuest,
middleware_on_response::Guest as OnResponseGuest,
};
use sgl::model_gateway::middleware_types::{Action, Request, Response};
/// Main middleware implementation
struct Middleware;
// Rate limit configuration
const RATE_LIMIT_REQUESTS: u64 = 60; // Maximum requests per window
const RATE_LIMIT_WINDOW_MS: u64 = 60_000; // Time window in milliseconds (1 minute)
// Simple in-memory counter (per WASM instance)
// In a real implementation, this would be shared across all instances
// This is a simplified example for demonstration purposes
struct RateLimitState {
requests: Vec<(String, u64)>, // (identifier, timestamp_ms)
}
impl RateLimitState {
fn new() -> Self {
Self {
requests: Vec::new(),
}
}
// Clean up old entries outside the time window
fn cleanup(&mut self, current_time_ms: u64) {
let cutoff = current_time_ms.saturating_sub(RATE_LIMIT_WINDOW_MS);
self.requests.retain(|(_, timestamp)| *timestamp > cutoff);
}
// Check if identifier has exceeded rate limit
fn check_limit(&mut self, identifier: &str, current_time_ms: u64) -> bool {
self.cleanup(current_time_ms);
// Count requests in current window for this identifier
let count = self
.requests
.iter()
.filter(|(id, timestamp)| {
id == identifier
&& *timestamp > current_time_ms.saturating_sub(RATE_LIMIT_WINDOW_MS)
})
.count() as u64;
if count >= RATE_LIMIT_REQUESTS {
return false; // Limit exceeded
}
// Add new request
self.requests
.push((identifier.to_string(), current_time_ms));
true // Within limit
}
}
// Thread-local state (per WASM instance thread)
// Using thread_local! is safer than static mut as it avoids unsafe blocks
// and provides separate state for each thread automatically
thread_local! {
static RATE_LIMIT_STATE: RefCell<RateLimitState> = RefCell::new(RateLimitState::new());
}
fn get_identifier(req: &Request) -> String {
// Helper function to find header value
let find_header_value =
|headers: &[sgl::model_gateway::middleware_types::Header], name: &str| -> Option<String> {
headers
.iter()
.find(|h| h.name.eq_ignore_ascii_case(name))
.map(|h| h.value.clone())
};
// Prefer API Key as identifier (more stable than IP)
if let Some(auth_header) = find_header_value(&req.headers, "authorization") {
if auth_header.starts_with("Bearer ") {
return format!("api_key:{}", &auth_header[7..]);
} else if auth_header.starts_with("ApiKey ") {
return format!("api_key:{}", &auth_header[7..]);
}
}
if let Some(api_key) = find_header_value(&req.headers, "x-api-key") {
return format!("api_key:{}", api_key);
}
// Fall back to IP address from forwarded headers
if let Some(forwarded_for) = find_header_value(&req.headers, "x-forwarded-for") {
// Take first IP from comma-separated list
let ip = forwarded_for.split(',').next().unwrap_or("").trim();
if !ip.is_empty() {
return format!("ip:{}", ip);
}
}
if let Some(real_ip) = find_header_value(&req.headers, "x-real-ip") {
return format!("ip:{}", real_ip);
}
// Last resort: use request ID (not ideal, but better than nothing)
format!("req_id:{}", req.request_id)
}
// Implement on-request interface
impl OnRequestGuest for Middleware {
fn on_request(req: Request) -> Action {
let identifier = get_identifier(&req);
let current_time_ms = req.now_epoch_ms;
// Access thread-local state safely without unsafe blocks
// Each thread gets its own RateLimitState instance
RATE_LIMIT_STATE.with(|state| {
let mut state = state.borrow_mut();
if !state.check_limit(&identifier, current_time_ms) {
// Rate limit exceeded
return Action::Reject(429);
}
// Within rate limit, continue processing
Action::Continue
})
}
}
// Implement on-response interface (empty - not used for rate limiting)
impl OnResponseGuest for Middleware {
fn on_response(_resp: Response) -> Action {
Action::Continue
}
}
// Export the component
export!(Middleware);