· 4 years ago · Jun 27, 2021, 03:10 PM
1// main.rs
2#![feature(proc_macro_hygiene, decl_macro)]
3
4use rocket::{get, routes};
5mod request_guard;
6
7#[get("/protected")]
8fn protected(key: request_guard::ApiKey) -> String {
9 format!("You are allowed to access this API because you presented key '{}'", key.0)
10}
11
12fn main() {
13 rocket::ignite().mount("/", routes![
14 protected,
15 ]).launch();
16}
17
18// request_guard.cs
19
20use rocket;
21use rocket::request::{self, Request, FromRequest, Outcome};
22use rocket::http::Status;
23
24#[derive(Debug)]
25pub struct ApiKey(pub String);
26
27#[derive(Debug)]
28pub enum ApiKeyError {
29 MissingKey,
30 InvalidKey,
31 MalformedKey,
32}
33
34impl<'a, 'r> FromRequest<'a, 'r> for ApiKey {
35 type Error = ApiKeyError;
36
37 fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
38 match request.headers().get_one("x-api-key") {
39 Some(s) => match base64::decode(s) {
40 Ok(decoded_key) => validate_api_key(decoded_key),
41 Err(_) => Outcome::Failure((Status::Unauthorized, ApiKeyError::InvalidKey)),
42 },
43 None => Outcome::Failure((Status::Unauthorized, ApiKeyError::MissingKey))
44 }
45 }
46}
47
48fn validate_api_key(key: Vec<u8>) -> Outcome<ApiKey, ApiKeyError> {
49 // Outcome::Success(ApiKey(std::str::from_utf8(&decoded_key).unwrap().to_owned()))
50
51 let decoded = std::str::from_utf8(&key);
52
53 match decoded {
54 Ok(s) => Outcome::Success(ApiKey(s.to_owned())),
55 Err(_e) => Outcome::Failure((Status::Unauthorized, ApiKeyError::MalformedKey)),
56 }
57}