actix_jwt_auth_middleware_derive/
lib.rs

1/*!
2This crate provides a derive macro for the [FromRequest](actix_web::FromRequest) trait.
3*/
4
5use derive_elves::type_aware_impl;
6use proc_macro::TokenStream;
7use quote::quote;
8use syn::parse_macro_input;
9use syn::DeriveInput;
10use syn::Ident;
11
12/**
13This macro implements the [FromRequest](actix_web::FromRequest) trait for the annotated type.
14
15## Example
16
17```rust
18# use actix_jwt_auth_middleware_derive::FromRequest;
19#
20#[derive(Clone, FromRequest)]
21struct UserClaims {
22    id: u32,
23    role: Role,
24}
25
26#[derive(Clone, FromRequest)]
27enum Role {
28    User,
29    Admin
30}
31*/
32#[proc_macro_derive(FromRequest)]
33pub fn from_request(tokenstream: TokenStream) -> TokenStream {
34    let input = parse_macro_input!(tokenstream as DeriveInput);
35    let ident = &input.ident;
36
37    let lower_case_ident = Ident::new(&ident.to_string().to_lowercase(), ident.span());
38
39    let error = format!(
40        "could not extract type \"{}\" from HttpRequest extensions",
41        ident.to_string()
42    );
43
44    type_aware_impl(
45        quote!(
46            // stolen from https://stackoverflow.com/questions/63673447/how-can-i-pass-structs-from-an-actix-middleware-to-the-handler
47
48            impl actix_web::FromRequest for #ident { // works
49                type Error = ::actix_web::Error;
50                type Future = std::future::Ready<Result<Self, Self::Error>>;
51                fn from_request(req: &actix_web::HttpRequest, _: &mut actix_web::dev::Payload) -> Self::Future {
52                    std::future::ready(
53                        match <actix_web::HttpRequest as actix_web::HttpMessage>::extensions(req).get::<#ident>() {
54                            Some(#lower_case_ident) => Ok(#lower_case_ident.clone()),
55                            None => Err(actix_web::error::ErrorBadRequest(#error))
56                        }
57                    )
58                }
59            }
60        ), 
61        &input
62    )
63    .into()
64}