6
6
7
7
use axum:: {
8
8
handler:: HandlerWithoutStateExt ,
9
- http:: { StatusCode , Uri } ,
9
+ http:: { uri :: Authority , StatusCode , Uri } ,
10
10
response:: Redirect ,
11
11
routing:: get,
12
12
BoxError , Router ,
@@ -106,7 +106,7 @@ async fn redirect_http_to_https<F>(ports: Ports, signal: F)
106
106
where
107
107
F : Future < Output = ( ) > + Send + ' static ,
108
108
{
109
- fn make_https ( host : String , uri : Uri , ports : Ports ) -> Result < Uri , BoxError > {
109
+ fn make_https ( host : & str , uri : Uri , https_port : u16 ) -> Result < Uri , BoxError > {
110
110
let mut parts = uri. into_parts ( ) ;
111
111
112
112
parts. scheme = Some ( axum:: http:: uri:: Scheme :: HTTPS ) ;
@@ -115,14 +115,24 @@ where
115
115
parts. path_and_query = Some ( "/" . parse ( ) . unwrap ( ) ) ;
116
116
}
117
117
118
- let https_host = host. replace ( & ports. http . to_string ( ) , & ports. https . to_string ( ) ) ;
119
- parts. authority = Some ( https_host. parse ( ) ?) ;
118
+ let authority: Authority = host. parse ( ) ?;
119
+ let bare_host = match authority. port ( ) {
120
+ Some ( port_struct) => authority
121
+ . as_str ( )
122
+ . strip_suffix ( port_struct. as_str ( ) )
123
+ . unwrap ( )
124
+ . strip_suffix ( ':' )
125
+ . unwrap ( ) , // if authority.port() is Some(port) then we can be sure authority ends with :{port}
126
+ None => authority. as_str ( ) ,
127
+ } ;
128
+
129
+ parts. authority = Some ( format ! ( "{bare_host}:{https_port}" ) . parse ( ) ?) ;
120
130
121
131
Ok ( Uri :: from_parts ( parts) ?)
122
132
}
123
133
124
134
let redirect = move |Host ( host) : Host , uri : Uri | async move {
125
- match make_https ( host, uri, ports) {
135
+ match make_https ( & host, uri, ports. https ) {
126
136
Ok ( uri) => Ok ( Redirect :: permanent ( & uri. to_string ( ) ) ) ,
127
137
Err ( error) => {
128
138
tracing:: warn!( %error, "failed to convert URI to HTTPS" ) ;
0 commit comments