swadhinbiswas

[email protected]
2026-07-25 16:28:21 +0600 committed NaN years ago
a66ecb8
commit a66ecb8
5 files changed
+30 -27
β–Όcrates/justapi-cli/src/main.rs
+3-6
372
372
fn prompt_db_selection(name: &str) -> (String, String) {
373
373
use std::io::{IsTerminal, Write};
374
374
if std::io::stdin().is_terminal() && std::io::stdout().is_terminal() {
375
- println!("πŸš€ Welcome to JustAPI Project Scaffolder!");
375
+ println!("Welcome to JustAPI Project Scaffolder!");
376
376
println!("Select a database backend for '{name}':");
377
377
println!(" Relational (Transactional SQL / OLTP):");
378
378
println!(" [1] SQLite (Zero-config, embedded file database) [default]");
1088
1088
),
1089
1089
)?;
1090
1090
1091
- println!(
1092
- "✨ Created new JustAPI project '{}' (API: {}, database: {})",
1093
- name, api_type, db_kind
1094
- );
1091
+ println!("Created new JustAPI project '{}' (API: {}, database: {})", name, api_type, db_kind);
1095
1092
println!(" └─ OpenTelemetry observability compose file: docker-compose.otel.yml");
1096
1093
println!();
1097
1094
println!(" cd {}", project_dir.display());
1762
1759
}
1763
1760
1764
1761
Commands::Profile { addr, duration, connections, output } => {
1765
- println!("πŸ”¬ JustAPI Profiler");
1762
+ println!("JustAPI Profiler");
1766
1763
println!(" Target: {addr}");
1767
1764
println!(" Duration: {duration}s");
1768
1765
println!(" Connections: {connections}");
1769
1766
β–Όcrates/justapi-core/src/middleware.rs
+25-16
384
384
let mut resp = next.run(req).await?;
385
385
let headers = resp.headers_mut();
386
386
387
- headers.insert("x-content-type-options", "nosniff".parse().unwrap());
387
+ headers.insert("x-content-type-options", HeaderValue::from_static("nosniff"));
388
388
389
389
if self.include_xfo {
390
- headers.insert("x-frame-options", "DENY".parse().unwrap());
390
+ headers.insert("x-frame-options", HeaderValue::from_static("DENY"));
391
391
}
392
392
393
- let hsts_val = if self.include_hsts_preload {
394
- format!("{}; preload", self.hsts.trim_end_matches("; preload"))
395
- } else {
396
- self.hsts.clone()
397
- };
398
393
if self.include_hsts {
399
- headers.insert("strict-transport-security", hsts_val.parse().unwrap());
394
+ let hsts_val = if self.include_hsts_preload {
395
+ format!("{}; preload", self.hsts.trim_end_matches("; preload"))
396
+ } else {
397
+ self.hsts.clone()
398
+ };
399
+ headers.insert(
400
+ "strict-transport-security",
401
+ HeaderValue::from_str(&hsts_val)
402
+ .map_err(|e| anyhow::anyhow!("invalid HSTS value: {e}"))?,
403
+ );
400
404
}
401
405
402
406
if self.include_csp {
403
407
let csp = self.csp_directives.join("; ");
404
- headers.insert("content-security-policy", csp.parse().unwrap());
408
+ headers.insert(
409
+ "content-security-policy",
410
+ HeaderValue::from_str(&csp)
411
+ .map_err(|e| anyhow::anyhow!("invalid CSP value: {e}"))?,
412
+ );
405
413
}
406
414
407
- headers.insert("x-xss-protection", "0".parse().unwrap());
415
+ headers.insert("x-xss-protection", HeaderValue::from_static("0"));
408
416
Ok(resp)
409
417
}
410
418
}
662
670
663
671
impl RateLimiter {
664
672
pub fn new(duration: std::time::Duration, max_burst: u32) -> Self {
673
+ let burst = NonZeroU32::new(max_burst).unwrap_or(NonZeroU32::MIN);
665
674
let quota = governor::Quota::with_period(duration)
666
- .unwrap()
667
- .allow_burst(NonZeroU32::new(max_burst).unwrap());
675
+ .expect("valid rate-limit duration")
676
+ .allow_burst(burst);
668
677
Self { limiter: governor::RateLimiter::direct(quota) }
669
678
}
670
679
747
756
let wait = negative.wait_time_from(now);
748
757
let retry_after_secs = wait.as_secs().max(1);
749
758
let mut resp = json_error(StatusCode::TOO_MANY_REQUESTS, "rate limit exceeded");
750
- resp.headers_mut()
751
- .insert("retry-after", retry_after_secs.to_string().parse().unwrap());
752
- resp.headers_mut()
753
- .insert("x-ratelimit-reset", retry_after_secs.to_string().parse().unwrap());
759
+ let retry_val = HeaderValue::from_str(&retry_after_secs.to_string())
760
+ .map_err(|e| anyhow::anyhow!("invalid retry-after: {e}"))?;
761
+ resp.headers_mut().insert("retry-after", retry_val.clone());
762
+ resp.headers_mut().insert("x-ratelimit-reset", retry_val);
754
763
Ok(resp)
755
764
}
756
765
}
757
766
β–Όcrates/justapi-core/src/server/mod.rs
+1-1
958
958
return res;
959
959
}
960
960
961
- tracing::info!("πŸš€ JustAPI serving on http://{}", local_addr);
961
+ tracing::info!("JustAPI serving on http://{}", local_addr);
962
962
tracing::info!(" ready β€” endpoints live at http://{}/", local_addr);
963
963
#[cfg(feature = "ws")]
964
964
let res = serve_http(
965
965
β–Όcrates/justapi-py/python/justapi/cli.py
+1-1
12
12
print("justapi 2.0.0")
13
13
return
14
14
15
- print("πŸš€ JustAPI Runtime v2.0.0 (Python package)")
15
+ print("JustAPI Runtime v2.0.0 (Python package)")
16
16
print("Commands:")
17
17
print(" justapi --version Display version")
18
18
print(" python -m app.main Run application directly")
19
19
β–Όcrates/justapi-py/src/request.rs
+0-3
198
198
auth_claims: Option<String>,
199
199
) -> Self {
200
200
let state = PyDict::new(py);
201
- // Bridge JWT claims from the Rust middleware into request.state["auth"].
202
- // The `auth_claims` is a JSON string of the decoded JWT payload, set by
203
- // the middleware and forwarded through `call_python_handler`.
204
201
if let Some(claims_json) = &auth_claims {
205
202
if let Ok(serde_json::Value::Object(map)) =
206
203
serde_json::from_str::<serde_json::Value>(claims_json)
207
204