diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md
index 8ee787c0..04bbb4de 100644
--- a/actix-web-codegen/CHANGES.md
+++ b/actix-web-codegen/CHANGES.md
@@ -1,6 +1,9 @@
 # Changes
 
 ## Unreleased - 2021-xx-xx
+- Fix support for guard paths in route handler macros. [#2771]
+
+[#2771] https://github.com/actix/actix-web/pull/2771
 
 
 ## 4.0.0 - 2022-02-24
diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs
index cb1ba1ef..cae3cbd5 100644
--- a/actix-web-codegen/src/route.rs
+++ b/actix-web-codegen/src/route.rs
@@ -4,7 +4,7 @@ use actix_router::ResourceDef;
 use proc_macro::TokenStream;
 use proc_macro2::{Span, TokenStream as TokenStream2};
 use quote::{format_ident, quote, ToTokens, TokenStreamExt};
-use syn::{parse_macro_input, AttributeArgs, Ident, LitStr, NestedMeta};
+use syn::{parse_macro_input, AttributeArgs, Ident, LitStr, NestedMeta, Path};
 
 enum ResourceType {
     Async,
@@ -77,7 +77,7 @@ impl TryFrom<&syn::LitStr> for MethodType {
 struct Args {
     path: syn::LitStr,
     resource_name: Option<syn::LitStr>,
-    guards: Vec<Ident>,
+    guards: Vec<Path>,
     wrappers: Vec<syn::Type>,
     methods: HashSet<MethodType>,
 }
@@ -121,7 +121,7 @@ impl Args {
                         }
                     } else if nv.path.is_ident("guard") {
                         if let syn::Lit::Str(lit) = nv.lit {
-                            guards.push(Ident::new(&lit.value(), Span::call_site()));
+                            guards.push(lit.parse::<Path>()?);
                         } else {
                             return Err(syn::Error::new_spanned(
                                 nv.lit,
diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/test_macro.rs
index 769cf2bc..55c2417b 100644
--- a/actix-web-codegen/tests/test_macro.rs
+++ b/actix-web-codegen/tests/test_macro.rs
@@ -96,6 +96,21 @@ async fn custom_resource_name_test<'a>(req: actix_web::HttpRequest) -> impl Resp
     HttpResponse::Ok()
 }
 
+mod guard_module {
+    use actix_web::{guard::GuardContext, http::header};
+
+    pub fn guard(ctx: &GuardContext) -> bool {
+        ctx.header::<header::Accept>()
+            .map(|h| h.preference() == "image/*")
+            .unwrap_or(false)
+    }
+}
+
+#[get("/test/guard", guard = "guard_module::guard")]
+async fn guard_test() -> impl Responder {
+    HttpResponse::Ok()
+}
+
 pub struct ChangeStatusCode;
 
 impl<S, B> Transform<S, ServiceRequest> for ChangeStatusCode
@@ -187,6 +202,7 @@ async fn test_body() {
             .service(test_handler)
             .service(route_test)
             .service(custom_resource_name_test)
+            .service(guard_test)
     });
     let request = srv.request(http::Method::GET, srv.url("/test"));
     let response = request.send().await.unwrap();
@@ -245,6 +261,12 @@ async fn test_body() {
     let request = srv.request(http::Method::GET, srv.url("/custom_resource_name"));
     let response = request.send().await.unwrap();
     assert!(response.status().is_success());
+
+    let request = srv
+        .request(http::Method::GET, srv.url("/test/guard"))
+        .insert_header(("Accept", "image/*"));
+    let response = request.send().await.unwrap();
+    assert!(response.status().is_success());
 }
 
 #[actix_rt::test]