@@ -11,19 +11,24 @@ use axum::{
11
11
response:: { IntoResponse , Response as AxumResponse } ,
12
12
} ;
13
13
use http:: header:: CONTENT_LENGTH ;
14
- use iron:: { headers:: ContentType , response:: Response , status:: Status , IronResult , Request } ;
14
+ use iron:: {
15
+ headers:: { ContentType , Link , LinkValue , RelationType } ,
16
+ response:: Response ,
17
+ status:: Status ,
18
+ IronResult , Request ,
19
+ } ;
15
20
use serde:: Serialize ;
16
21
use std:: { borrow:: Cow , sync:: Arc } ;
17
22
use tera:: { Context , Tera } ;
18
23
19
24
/// When making using a custom status, use a closure that coerces to a `fn(&Self) -> Status`
20
25
#[ macro_export]
21
26
macro_rules! impl_webpage {
22
- ( $page: ty = $template: literal $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , ) ?) => {
23
- $crate:: impl_webpage!( $page = |_| :: std:: borrow:: Cow :: Borrowed ( $template) $( , status = $status) ? $( , content_type = $content_type) ?) ;
27
+ ( $page: ty = $template: literal $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $ ( , canonical_url = $canonical_url : expr ) ? $( , ) ?) => {
28
+ $crate:: impl_webpage!( $page = |_| :: std:: borrow:: Cow :: Borrowed ( $template) $( , status = $status) ? $( , content_type = $content_type) ? $ ( , canonical_url = $canonical_url ) ? ) ;
24
29
} ;
25
30
26
- ( $page: ty = $template: expr $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , ) ?) => {
31
+ ( $page: ty = $template: expr $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , canonical_url = $canonical_url : expr ) ? $ ( , ) ?) => {
27
32
impl $crate:: web:: page:: WebPage for $page {
28
33
fn template( & self ) -> :: std:: borrow:: Cow <' static , str > {
29
34
let template: fn ( & Self ) -> :: std:: borrow:: Cow <' static , str > = $template;
@@ -37,6 +42,14 @@ macro_rules! impl_webpage {
37
42
}
38
43
) ?
39
44
45
+
46
+ $(
47
+ fn canonical_url( & self ) -> Option <String > {
48
+ let canonical_url: fn ( & Self ) -> Option <String > = $canonical_url;
49
+ ( canonical_url) ( self )
50
+ }
51
+ ) ?
52
+
40
53
$(
41
54
fn content_type( ) -> :: iron:: headers:: ContentType {
42
55
$content_type
@@ -48,11 +61,11 @@ macro_rules! impl_webpage {
48
61
49
62
#[ macro_export]
50
63
macro_rules! impl_axum_webpage {
51
- ( $page: ty = $template: literal $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , ) ?) => {
52
- $crate:: impl_axum_webpage!( $page = |_| :: std:: borrow:: Cow :: Borrowed ( $template) $( , status = $status) ? $( , content_type = $content_type) ?) ;
64
+ ( $page: ty = $template: literal $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , canonical_url = $canonical_url : expr ) ? $ ( , ) ?) => {
65
+ $crate:: impl_axum_webpage!( $page = |_| :: std:: borrow:: Cow :: Borrowed ( $template) $( , status = $status) ? $( , content_type = $content_type) ? $ ( , canonical_url = $canonical_url : expr ) ? ) ;
53
66
} ;
54
67
55
- ( $page: ty = $template: expr $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , ) ?) => {
68
+ ( $page: ty = $template: expr $( , status = $status: expr) ? $( , content_type = $content_type: expr) ? $( , canonical_url = $canonical_url : expr ) ? $ ( , ) ?) => {
56
69
impl axum:: response:: IntoResponse for $page
57
70
{
58
71
fn into_response( self ) -> :: axum:: response:: Response {
@@ -134,12 +147,24 @@ pub trait WebPage: Serialize + Sized {
134
147
response. extensions . insert :: < CachePolicy > ( cache) ;
135
148
}
136
149
150
+ if let Some ( canonical_url) = self . canonical_url ( ) {
151
+ let link_value = LinkValue :: new ( canonical_url)
152
+ . push_rel ( RelationType :: ExtRelType ( "canonical" . to_string ( ) ) ) ;
153
+
154
+ response. headers . set ( Link :: new ( vec ! [ link_value] ) ) ;
155
+ }
156
+
137
157
Ok ( response)
138
158
}
139
159
140
160
/// The name of the template to be rendered
141
161
fn template ( & self ) -> Cow < ' static , str > ;
142
162
163
+ /// The canonical URL to set in response headers
164
+ fn canonical_url ( & self ) -> Option < String > {
165
+ None
166
+ }
167
+
143
168
/// Gets the status of the request, defaults to `Ok`
144
169
fn get_status ( & self ) -> Status {
145
170
Status :: Ok
0 commit comments