| Crates.io | oxify-server |
| lib.rs | oxify-server |
| version | 0.1.0 |
| created_at | 2026-01-19 04:47:25.784577+00 |
| updated_at | 2026-01-19 04:47:25.784577+00 |
| description | HTTP server implementation for OxiFY - Axum, graceful shutdown, middleware (ported from OxiRS) |
| homepage | |
| repository | https://github.com/cool-japan/oxify |
| max_upload_size | |
| id | 2053709 |
| size | 500,279 |
Production-ready HTTP server foundation for OxiFY, built on Axum and Tower.
oxify-server provides a robust, batteries-included HTTP server runtime for building LLM workflow APIs. It handles the operational concerns (logging, tracing, graceful shutdown, middleware) so you can focus on building workflow endpoints.
Ported from: OxiRS - Battle-tested in production semantic web applications.
[dependencies]
oxify-server = { path = "../crates/api/oxify-server" }
# Or with features
oxify-server = { path = "../crates/api/oxify-server", features = ["compression", "cors"] }
compression (default): HTTP response compression (gzip, brotli, deflate)cors (default): CORS middleware supportuse oxify_server::{ServerConfig, ServerRuntime};
use axum::{routing::get, Router, Json};
use serde_json::json;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create router
let app = Router::new()
.route("/", get(|| async {
Json(json!({"status": "ok"}))
}));
// Configure and run server
let config = ServerConfig::development();
let server = ServerRuntime::new(config).with_router(app);
server.run().await?;
Ok(())
}
use oxify_server::{ServerConfig, ServerRuntime, auth_middleware};
use oxify_authn::{JwtManager, JwtConfig};
use axum::{
routing::{get, post},
Router,
middleware,
};
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Initialize JWT manager
let jwt_config = JwtConfig::development();
let jwt_manager = Arc::new(JwtManager::new(&jwt_config)?);
// Build router with protected routes
let app = Router::new()
.route("/", get(public_handler))
.route("/protected", get(protected_handler))
.layer(middleware::from_fn_with_state(
jwt_manager.clone(),
auth_middleware,
))
.route("/login", post(login_handler))
.with_state(jwt_manager);
// Run server
let config = ServerConfig::development();
let server = ServerRuntime::new(config).with_router(app);
server.run().await?;
Ok(())
}
async fn public_handler() -> &'static str {
"Public endpoint"
}
async fn protected_handler() -> &'static str {
"Protected endpoint - requires valid JWT"
}
async fn login_handler() -> &'static str {
"Login endpoint"
}
ServerRuntimeMain server runtime that manages the Axum server lifecycle.
pub struct ServerRuntime {
config: ServerConfig,
router: Option<Router>,
}
impl ServerRuntime {
pub fn new(config: ServerConfig) -> Self;
pub fn with_router(self, router: Router) -> Self;
pub async fn run(self) -> Result<()>;
}
ServerConfigServer configuration with sensible defaults.
pub struct ServerConfig {
pub host: String,
pub port: u16,
pub request_logging: bool,
pub request_id_header: String,
pub cors: bool,
pub compression: bool,
pub graceful_shutdown_timeout_secs: u64,
}
impl ServerConfig {
pub fn development() -> Self; // localhost:3000, all features enabled
pub fn production() -> Self; // 0.0.0.0:8080, production settings
}
Development Config:
127.0.0.13000Production Config:
0.0.0.08080Automatically adds a unique request ID to each request.
use oxify_server::request_id_middleware;
let app = Router::new()
.route("/", get(handler))
.layer(axum::middleware::from_fn(request_id_middleware));
Request ID is available in:
x-request-idrequest.extensions().get::<RequestId>()Logs request/response details with structured tracing.
use oxify_server::logging_middleware;
let app = Router::new()
.route("/", get(handler))
.layer(axum::middleware::from_fn(logging_middleware));
Logs include:
JWT-based authentication middleware.
use oxify_server::auth_middleware;
use oxify_authn::JwtManager;
use std::sync::Arc;
let jwt_manager = Arc::new(JwtManager::new(&config)?);
let app = Router::new()
.route("/protected", get(handler))
.layer(middleware::from_fn_with_state(
jwt_manager.clone(),
auth_middleware,
));
Public routes (skip authentication):
/health/metrics/login/registerCross-origin resource sharing configuration.
use oxify_server::cors_layer;
let app = Router::new()
.route("/", get(handler))
.layer(cors_layer());
Default CORS settings:
use oxify_server::{ServerConfig, ServerRuntime};
use oxify_authn::{JwtManager, JwtConfig, User, Permission};
use axum::{
extract::State,
http::StatusCode,
routing::{get, post},
Router,
Json,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tracing::Level;
#[derive(Clone)]
struct AppState {
jwt_manager: Arc<JwtManager>,
}
#[derive(Deserialize)]
struct LoginRequest {
username: String,
password: String,
}
#[derive(Serialize)]
struct LoginResponse {
token: String,
user: User,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Initialize tracing
tracing_subscriber::fmt()
.with_max_level(Level::INFO)
.init();
// Initialize state
let jwt_config = JwtConfig::development();
let jwt_manager = Arc::new(JwtManager::new(&jwt_config)?);
let app_state = AppState { jwt_manager };
// Build application
let app = Router::new()
.route("/", get(root))
.route("/login", post(login))
.with_state(app_state);
// Run server
let config = ServerConfig::development();
let server = ServerRuntime::new(config).with_router(app);
tracing::info!("Server starting at http://127.0.0.1:3000");
server.run().await?;
Ok(())
}
async fn root() -> Json<serde_json::Value> {
Json(serde_json::json!({
"name": "OxiFY API",
"version": "0.1.0",
"status": "running"
}))
}
async fn login(
State(state): State<AppState>,
Json(req): Json<LoginRequest>,
) -> Result<Json<LoginResponse>, StatusCode> {
// In production, verify password against database
let user = User {
username: req.username.clone(),
roles: vec!["user".to_string()],
email: Some(format!("{}@example.com", req.username)),
full_name: Some(req.username.clone()),
last_login: Some(chrono::Utc::now()),
permissions: vec![Permission::Read, Permission::Write],
};
let token = state.jwt_manager
.generate_token(&user)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(Json(LoginResponse { token, user }))
}
The server automatically handles shutdown signals:
# Send SIGINT (Ctrl+C)
kill -INT <pid>
# Send SIGTERM
kill -TERM <pid>
Shutdown sequence:
Configure timeout:
let config = ServerConfig {
graceful_shutdown_timeout_secs: 60, // 60 second timeout
..ServerConfig::default()
};
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
COPY --from=builder /app/target/release/oxify-api /usr/local/bin/
EXPOSE 8080
CMD ["oxify-api"]
# Server configuration
export OXIFY_HOST="0.0.0.0"
export OXIFY_PORT="8080"
export OXIFY_LOG_LEVEL="info"
# Authentication
export JWT_SECRET="your-secret-key-min-32-bytes"
export JWT_EXPIRATION_SECS="3600"
# Database
export DATABASE_URL="postgresql://user:pass@localhost/oxify"
apiVersion: apps/v1
kind: Deployment
metadata:
name: oxify-api
spec:
replicas: 3
selector:
matchLabels:
app: oxify-api
template:
metadata:
labels:
app: oxify-api
spec:
containers:
- name: oxify-api
image: oxify/api:latest
ports:
- containerPort: 8080
env:
- name: OXIFY_HOST
value: "0.0.0.0"
- name: OXIFY_PORT
value: "8080"
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: oxify-secrets
key: jwt-secret
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
use axum::{routing::get, Router, Json};
let app = Router::new()
.route("/health", get(health_check));
async fn health_check() -> Json<serde_json::Value> {
Json(serde_json::json!({
"status": "healthy",
"timestamp": chrono::Utc::now().to_rfc3339()
}))
}
Integration with Prometheus metrics is planned:
use oxify_server::metrics_middleware;
let app = Router::new()
.route("/", get(handler))
.layer(metrics_middleware());
// Exposes /metrics endpoint with:
// - http_requests_total
// - http_request_duration_seconds
// - http_requests_in_flight
Run the test suite:
cd crates/api/oxify-server
cargo test
# Run with all features
cargo test --all-features
Core dependencies:
axum - Web frameworktower / tower-http - Middlewaretokio - Async runtimetracing - Structured loggingIntegration:
oxify-authn - Authentication middlewareoxify-authz - Authorization (future)Apache-2.0
Ported from OxiRS with permission. Original implementation by the OxiLabs team.