-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
h1.rs
96 lines (82 loc) · 2.74 KB
/
h1.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::fmt::Write;
use std::mem;
use std::sync::Arc;
use bytes::BytesMut;
use http;
use http::header::HOST;
use http::uri::{Authority, Parts, Scheme, Uri};
use ctx::transport::{Server as ServerCtx};
/// Sentinel extension to signal that we should tell hyper to serialize
/// the `Uri` in absolute-form.
pub struct UriIsAbsoluteForm;
/// Tries to make sure the `Uri` of the request is in a form needed by
/// hyper's Client.
///
/// Also sets the `UriIsAbsoluteForm` extension if received `Uri` was
/// already in absolute-form.
pub fn normalize_our_view_of_uri<B>(req: &mut http::Request<B>) {
if req.uri().authority_part().is_some() {
req.extensions_mut().insert(UriIsAbsoluteForm);
return;
}
// try to parse the Host header
if let Some(auth) = authority_from_host(&req) {
set_authority(req.uri_mut(), auth);
return;
}
// last resort is to use the so_original_dst
let orig_dst = req.extensions()
.get::<Arc<ServerCtx>>()
.and_then(|ctx| ctx.orig_dst_if_not_local());
if let Some(orig_dst) = orig_dst {
let mut bytes = BytesMut::with_capacity(31);
write!(&mut bytes, "{}", orig_dst)
.expect("socket address display is under 31 bytes");
let bytes = bytes.freeze();
let auth = Authority::from_shared(bytes)
.expect("socket address is valid authority");
set_authority(req.uri_mut(), auth);
}
}
/// Returns an Authority from a request's Host header.
pub fn authority_from_host<B>(req: &http::Request<B>) -> Option<Authority> {
req.headers().get(HOST)
.and_then(|host| {
host.to_str().ok()
.and_then(|s| {
if s.is_empty() {
None
} else {
s.parse::<Authority>().ok()
}
})
})
}
fn set_authority(uri: &mut http::Uri, auth: Authority) {
let mut parts = Parts::from(mem::replace(uri, Uri::default()));
parts.scheme = Some(Scheme::HTTP);
parts.authority = Some(auth);
let new = Uri::from_parts(parts)
.expect("absolute uri");
*uri = new;
}
pub fn strip_connection_headers(headers: &mut http::HeaderMap) {
let conn_val = if let Some(val) = headers.remove(http::header::CONNECTION) {
val
} else {
return
};
let conn_header = if let Ok(s) = conn_val.to_str() {
s
} else {
return
};
// A `Connection` header may have a comma-separated list of
// names of other headers that are meant for only this specific connection.
//
// Iterate these names and remove them as headers.
for name in conn_header.split(',') {
let name = name.trim();
headers.remove(name);
}
}