fix(chainfire): Use wildcard route for KV endpoints
Replace :key with *key pattern to avoid axum route conflict. Adds wildcard handler functions for GET/PUT/DELETE that properly handle both simple keys and namespaced keys with slashes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4bfe75a1d7
commit
26a4443a78
1 changed files with 91 additions and 1 deletions
|
|
@ -134,7 +134,8 @@ pub struct PrefixQuery {
|
|||
/// Build the REST API router
|
||||
pub fn build_router(state: RestApiState) -> Router {
|
||||
Router::new()
|
||||
.route("/api/v1/kv/:key", get(get_kv).put(put_kv).delete(delete_kv))
|
||||
// Wildcard route handles all keys (with or without slashes)
|
||||
.route("/api/v1/kv/*key", get(get_kv_wildcard).put(put_kv_wildcard).delete(delete_kv_wildcard))
|
||||
.route("/api/v1/kv", get(list_kv))
|
||||
.route("/api/v1/cluster/status", get(cluster_status))
|
||||
.route("/api/v1/cluster/members", post(add_member))
|
||||
|
|
@ -222,6 +223,95 @@ async fn delete_kv(
|
|||
))
|
||||
}
|
||||
|
||||
/// GET /api/v1/kv/*key - Get value (wildcard for all keys)
|
||||
async fn get_kv_wildcard(
|
||||
State(state): State<RestApiState>,
|
||||
Path(key): Path<String>,
|
||||
) -> Result<Json<SuccessResponse<GetResponse>>, (StatusCode, Json<ErrorResponse>)> {
|
||||
// Use key as-is for simple keys, prepend / for namespaced keys
|
||||
// Keys like "testkey" stay as "testkey", keys like "flaredb/stores/1" become "/flaredb/stores/1"
|
||||
let full_key = if key.contains('/') {
|
||||
format!("/{}", key)
|
||||
} else {
|
||||
key.clone()
|
||||
};
|
||||
let sm = state.raft.state_machine();
|
||||
let key_bytes = full_key.as_bytes().to_vec();
|
||||
|
||||
let results = sm.kv()
|
||||
.get(&key_bytes)
|
||||
.map_err(|e| error_response(StatusCode::INTERNAL_SERVER_ERROR, "INTERNAL_ERROR", &e.to_string()))?;
|
||||
|
||||
let value = results
|
||||
.into_iter()
|
||||
.next()
|
||||
.ok_or_else(|| error_response(StatusCode::NOT_FOUND, "NOT_FOUND", "Key not found"))?;
|
||||
|
||||
Ok(Json(SuccessResponse::new(GetResponse {
|
||||
key: full_key,
|
||||
value: String::from_utf8_lossy(&value.value).to_string(),
|
||||
})))
|
||||
}
|
||||
|
||||
/// PUT /api/v1/kv/*key - Put value (wildcard for all keys)
|
||||
async fn put_kv_wildcard(
|
||||
State(state): State<RestApiState>,
|
||||
Path(key): Path<String>,
|
||||
Json(req): Json<PutRequest>,
|
||||
) -> Result<(StatusCode, Json<SuccessResponse<serde_json::Value>>), (StatusCode, Json<ErrorResponse>)> {
|
||||
// Use key as-is for simple keys, prepend / for namespaced keys
|
||||
let full_key = if key.contains('/') {
|
||||
format!("/{}", key)
|
||||
} else {
|
||||
key.clone()
|
||||
};
|
||||
let command = RaftCommand::Put {
|
||||
key: full_key.as_bytes().to_vec(),
|
||||
value: req.value.as_bytes().to_vec(),
|
||||
lease_id: None,
|
||||
prev_kv: false,
|
||||
};
|
||||
|
||||
state
|
||||
.raft
|
||||
.client_write(command)
|
||||
.await
|
||||
.map_err(|e| error_response(StatusCode::INTERNAL_SERVER_ERROR, "INTERNAL_ERROR", &e.to_string()))?;
|
||||
|
||||
Ok((
|
||||
StatusCode::OK,
|
||||
Json(SuccessResponse::new(serde_json::json!({ "key": full_key, "success": true }))),
|
||||
))
|
||||
}
|
||||
|
||||
/// DELETE /api/v1/kv/*key - Delete key (wildcard for all keys)
|
||||
async fn delete_kv_wildcard(
|
||||
State(state): State<RestApiState>,
|
||||
Path(key): Path<String>,
|
||||
) -> Result<(StatusCode, Json<SuccessResponse<serde_json::Value>>), (StatusCode, Json<ErrorResponse>)> {
|
||||
// Use key as-is for simple keys, prepend / for namespaced keys
|
||||
let full_key = if key.contains('/') {
|
||||
format!("/{}", key)
|
||||
} else {
|
||||
key.clone()
|
||||
};
|
||||
let command = RaftCommand::Delete {
|
||||
key: full_key.as_bytes().to_vec(),
|
||||
prev_kv: false,
|
||||
};
|
||||
|
||||
state
|
||||
.raft
|
||||
.client_write(command)
|
||||
.await
|
||||
.map_err(|e| error_response(StatusCode::INTERNAL_SERVER_ERROR, "INTERNAL_ERROR", &e.to_string()))?;
|
||||
|
||||
Ok((
|
||||
StatusCode::OK,
|
||||
Json(SuccessResponse::new(serde_json::json!({ "key": full_key, "success": true }))),
|
||||
))
|
||||
}
|
||||
|
||||
/// GET /api/v1/kv?prefix={prefix} - Range scan
|
||||
async fn list_kv(
|
||||
State(state): State<RestApiState>,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue