fix(starter-rust): fix compilation errors in Rust starter kit
- Add Clone derive to AppState for axum compatibility - Import Digest trait from sha2 for hash computation - Use String instead of &str in response headers for lifetime safety - Add Position import to grid.rs module - Make Position Copy for easier cloning - Replace constant_time_eq with custom hmac_equal function - Add musl-dev to Dockerfile for Alpine build compatibility The Rust starter kit now compiles and builds successfully with cargo check and Docker, matching the requirements from plan §5.3 and §12 (Phase 2). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
7694723758
commit
b60b103c0f
4 changed files with 23 additions and 16 deletions
|
|
@ -1 +1 @@
|
|||
b31c306013e5d99cdf1224c14c7ff887139f187d
|
||||
dff235e19318f50109a3f29edcd1f01b6cc94857
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ WORKDIR /app
|
|||
COPY Cargo.toml ./
|
||||
COPY src ./src
|
||||
|
||||
RUN cargo build --release
|
||||
RUN apk add --no-cache musl-dev && cargo build --release
|
||||
|
||||
FROM alpine:3.21
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
//! Provides toroidal distance calculations, neighbor enumeration,
|
||||
//! and BFS pathfinding on a wrapping grid.
|
||||
|
||||
use crate::Position;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
/// Manhattan distance with wrap-around on a toroidal grid.
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ use axum::{
|
|||
extract::State,
|
||||
http::{HeaderMap, StatusCode},
|
||||
routing::{get, post},
|
||||
Json, Router,
|
||||
Router,
|
||||
};
|
||||
use hmac::{Hmac, Mac};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::Sha256;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::env;
|
||||
|
||||
type HmacSha256 = Hmac<Sha256>;
|
||||
|
|
@ -57,7 +57,7 @@ struct You {
|
|||
score: u32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
#[derive(Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Position {
|
||||
pub row: u32,
|
||||
pub col: u32,
|
||||
|
|
@ -87,6 +87,7 @@ struct Move {
|
|||
direction: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
secret: String,
|
||||
}
|
||||
|
|
@ -117,7 +118,7 @@ async fn handle_turn(
|
|||
State(state): State<AppState>,
|
||||
headers: HeaderMap,
|
||||
body: Bytes,
|
||||
) -> Result<(StatusCode, [(&str, String); 2], String), StatusCode> {
|
||||
) -> Result<(StatusCode, [(String, String); 2], String), StatusCode> {
|
||||
let signature = headers
|
||||
.get("X-ACB-Signature")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
|
|
@ -171,8 +172,8 @@ async fn handle_turn(
|
|||
Ok((
|
||||
StatusCode::OK,
|
||||
[
|
||||
("Content-Type".to_string(), "application/json".to_string()),
|
||||
("X-ACB-Signature".to_string(), response_sig),
|
||||
("Content-Type".to_owned(), "application/json".to_owned()),
|
||||
("X-ACB-Signature".to_owned(), response_sig),
|
||||
],
|
||||
response_body,
|
||||
))
|
||||
|
|
@ -241,7 +242,6 @@ fn verify_signature(
|
|||
body: &[u8],
|
||||
signature: &str,
|
||||
) -> bool {
|
||||
use hex::FromHex;
|
||||
let body_hash = sha2::Sha256::digest(body);
|
||||
let signing_string = format!(
|
||||
"{}.{}.{}.{}",
|
||||
|
|
@ -254,15 +254,21 @@ fn verify_signature(
|
|||
let mut mac =
|
||||
HmacSha256::new_from_slice(secret.as_bytes()).expect("HMAC key error");
|
||||
mac.update(signing_string.as_bytes());
|
||||
let expected = mac.finalize().into_bytes();
|
||||
let expected = hex::encode(mac.finalize().into_bytes());
|
||||
|
||||
match Vec::from_hex(signature) {
|
||||
Ok(sig_bytes) => {
|
||||
let sig_truncated: &[u8] = &sig_bytes;
|
||||
hmac::digest::constant_time_eq(sig_truncated, &expected)
|
||||
}
|
||||
Err(_) => false,
|
||||
hmac_equal(signature, &expected)
|
||||
}
|
||||
|
||||
/// Constant-time string comparison
|
||||
fn hmac_equal(a: &str, b: &str) -> bool {
|
||||
if a.len() != b.len() {
|
||||
return false;
|
||||
}
|
||||
a.as_bytes()
|
||||
.iter()
|
||||
.zip(b.as_bytes().iter())
|
||||
.fold(0, |acc, (x, y)| acc | (x ^ y))
|
||||
== 0
|
||||
}
|
||||
|
||||
fn sign_response(secret: &str, match_id: &str, turn: u32, body: &[u8]) -> String {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue