mirror of
https://github.com/fafhrd91/actix-web
synced 2025-01-18 13:51:50 +01:00
added ConnectionInfo
This commit is contained in:
parent
d8b880e167
commit
c3de32c3b3
@ -42,8 +42,8 @@ fn main() {
|
|||||||
.header("LOCATION", "/index.html")
|
.header("LOCATION", "/index.html")
|
||||||
.body(Body::Empty)
|
.body(Body::Empty)
|
||||||
})))
|
})))
|
||||||
.serve_tls::<_, ()>("127.0.0.1:8080", pkcs12).unwrap();
|
.serve_tls::<_, ()>("127.0.0.1:8443", pkcs12).unwrap();
|
||||||
|
|
||||||
println!("Started http server: 127.0.0.1:8080");
|
println!("Started http server: 127.0.0.1:8443");
|
||||||
let _ = sys.run();
|
let _ = sys.run();
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,14 @@ use url::form_urlencoded;
|
|||||||
use http::{header, Uri, Method, Version, HeaderMap, Extensions};
|
use http::{header, Uri, Method, Version, HeaderMap, Extensions};
|
||||||
|
|
||||||
use {Cookie, HttpRange};
|
use {Cookie, HttpRange};
|
||||||
|
use info::ConnectionInfo;
|
||||||
use recognizer::Params;
|
use recognizer::Params;
|
||||||
use payload::Payload;
|
use payload::Payload;
|
||||||
use multipart::Multipart;
|
use multipart::Multipart;
|
||||||
use error::{ParseError, PayloadError,
|
use error::{ParseError, PayloadError,
|
||||||
MultipartError, CookieParseError, HttpRangeError, UrlencodedError};
|
MultipartError, CookieParseError, HttpRangeError, UrlencodedError};
|
||||||
|
|
||||||
|
|
||||||
struct HttpMessage {
|
struct HttpMessage {
|
||||||
version: Version,
|
version: Version,
|
||||||
method: Method,
|
method: Method,
|
||||||
@ -27,6 +29,7 @@ struct HttpMessage {
|
|||||||
cookies_loaded: bool,
|
cookies_loaded: bool,
|
||||||
addr: Option<SocketAddr>,
|
addr: Option<SocketAddr>,
|
||||||
payload: Payload,
|
payload: Payload,
|
||||||
|
info: Option<ConnectionInfo<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for HttpMessage {
|
impl Default for HttpMessage {
|
||||||
@ -44,6 +47,7 @@ impl Default for HttpMessage {
|
|||||||
addr: None,
|
addr: None,
|
||||||
payload: Payload::empty(),
|
payload: Payload::empty(),
|
||||||
extensions: Extensions::new(),
|
extensions: Extensions::new(),
|
||||||
|
info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,6 +74,7 @@ impl HttpRequest<()> {
|
|||||||
addr: None,
|
addr: None,
|
||||||
payload: payload,
|
payload: payload,
|
||||||
extensions: Extensions::new(),
|
extensions: Extensions::new(),
|
||||||
|
info: None,
|
||||||
}),
|
}),
|
||||||
Rc::new(())
|
Rc::new(())
|
||||||
)
|
)
|
||||||
@ -106,6 +111,15 @@ impl<S> HttpRequest<S> {
|
|||||||
&mut self.as_mut().extensions
|
&mut self.as_mut().extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_prefix(&mut self, idx: usize) {
|
||||||
|
self.as_mut().prefix = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn prefix_len(&self) -> usize {
|
||||||
|
self.0.prefix
|
||||||
|
}
|
||||||
|
|
||||||
/// Read the Request Uri.
|
/// Read the Request Uri.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn uri(&self) -> &Uri { &self.0.uri }
|
pub fn uri(&self) -> &Uri { &self.0.uri }
|
||||||
@ -132,13 +146,15 @@ impl<S> HttpRequest<S> {
|
|||||||
self.0.uri.path()
|
self.0.uri.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_prefix(&mut self, idx: usize) {
|
/// Load *ConnectionInfo* for currect request.
|
||||||
self.as_mut().prefix = idx;
|
#[inline]
|
||||||
|
pub fn load_connection_info(&mut self) -> &ConnectionInfo {
|
||||||
|
if self.0.info.is_none() {
|
||||||
|
let info: ConnectionInfo<'static> = unsafe{
|
||||||
|
mem::transmute(ConnectionInfo::new(self))};
|
||||||
|
self.as_mut().info = Some(info);
|
||||||
}
|
}
|
||||||
|
self.0.info.as_ref().unwrap()
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn prefix_len(&self) -> usize {
|
|
||||||
self.0.prefix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remote IP of client initiated HTTP request.
|
/// Remote IP of client initiated HTTP request.
|
||||||
|
148
src/info.rs
Normal file
148
src/info.rs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
use http::header::{self, HeaderName};
|
||||||
|
use httprequest::HttpRequest;
|
||||||
|
|
||||||
|
const X_FORWARDED_HOST: &str = "X-FORWARDED-HOST";
|
||||||
|
const X_FORWARDED_PROTO: &str = "X-FORWARDED-PROTO";
|
||||||
|
|
||||||
|
|
||||||
|
/// `HttpRequest` connection information
|
||||||
|
///
|
||||||
|
/// While it is possible to create `ConnectionInfo` directly,
|
||||||
|
/// consider using `HttpRequest::load_connection_info()` which cache result.
|
||||||
|
pub struct ConnectionInfo<'a> {
|
||||||
|
scheme: &'a str,
|
||||||
|
host: &'a str,
|
||||||
|
remote: String,
|
||||||
|
forwarded_for: Vec<&'a str>,
|
||||||
|
forwarded_by: Vec<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ConnectionInfo<'a> {
|
||||||
|
|
||||||
|
/// Create *ConnectionInfo* instance for a request.
|
||||||
|
pub fn new<S>(req: &'a HttpRequest<S>) -> ConnectionInfo<'a> {
|
||||||
|
let mut host = None;
|
||||||
|
let mut scheme = None;
|
||||||
|
let mut forwarded_for = Vec::new();
|
||||||
|
let mut forwarded_by = Vec::new();
|
||||||
|
|
||||||
|
// load forwarded header
|
||||||
|
for hdr in req.headers().get_all(header::FORWARDED) {
|
||||||
|
if let Ok(val) = hdr.to_str() {
|
||||||
|
for pair in val.split(';') {
|
||||||
|
for el in pair.split(',') {
|
||||||
|
let mut items = el.splitn(1, '=');
|
||||||
|
if let Some(name) = items.next() {
|
||||||
|
if let Some(val) = items.next() {
|
||||||
|
match &name.to_lowercase() as &str {
|
||||||
|
"for" => forwarded_for.push(val.trim()),
|
||||||
|
"by" => forwarded_by.push(val.trim()),
|
||||||
|
"proto" => if scheme.is_none() {
|
||||||
|
scheme = Some(val.trim());
|
||||||
|
},
|
||||||
|
"host" => if host.is_none() {
|
||||||
|
host = Some(val.trim());
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scheme
|
||||||
|
if scheme.is_none() {
|
||||||
|
if let Some(h) = req.headers().get(
|
||||||
|
HeaderName::from_str(X_FORWARDED_PROTO).unwrap()) {
|
||||||
|
if let Ok(h) = h.to_str() {
|
||||||
|
scheme = h.split(',').next().map(|v| v.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if scheme.is_none() {
|
||||||
|
if let Some(a) = req.uri().scheme_part() {
|
||||||
|
scheme = Some(a.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// host
|
||||||
|
if host.is_none() {
|
||||||
|
if let Some(h) = req.headers().get(HeaderName::from_str(X_FORWARDED_HOST).unwrap()) {
|
||||||
|
if let Ok(h) = h.to_str() {
|
||||||
|
host = h.split(',').next().map(|v| v.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if host.is_none() {
|
||||||
|
if let Some(h) = req.headers().get(header::HOST) {
|
||||||
|
if let Ok(h) = h.to_str() {
|
||||||
|
host = Some(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if host.is_none() {
|
||||||
|
if let Some(a) = req.uri().authority_part() {
|
||||||
|
host = Some(a.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionInfo {
|
||||||
|
scheme: scheme.unwrap_or("http"),
|
||||||
|
host: host.unwrap_or("localhost"),
|
||||||
|
remote: String::new(),
|
||||||
|
forwarded_for: forwarded_for,
|
||||||
|
forwarded_by: forwarded_by,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Scheme of the request.
|
||||||
|
///
|
||||||
|
/// Scheme is resolved through the following headers, in this order:
|
||||||
|
///
|
||||||
|
/// - Forwarded
|
||||||
|
/// - X-Forwarded-Proto
|
||||||
|
/// - Uri
|
||||||
|
#[inline]
|
||||||
|
pub fn scheme(&self) -> &str {
|
||||||
|
self.scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hostname of the request.
|
||||||
|
///
|
||||||
|
/// Hostname is resolved through the following headers, in this order:
|
||||||
|
///
|
||||||
|
/// - Forwarded
|
||||||
|
/// - X-Forwarded-Host
|
||||||
|
/// - Host
|
||||||
|
/// - Uri
|
||||||
|
pub fn host(&self) -> &str {
|
||||||
|
self.host
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remote IP of client initiated HTTP request.
|
||||||
|
///
|
||||||
|
/// The IP is resolved through the following headers, in this order:
|
||||||
|
///
|
||||||
|
/// - Forwarded
|
||||||
|
/// - X-Forwarded-For
|
||||||
|
/// - peername of opened socket
|
||||||
|
#[inline]
|
||||||
|
pub fn remote(&self) -> &str {
|
||||||
|
&self.remote
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List of the nodes making the request to the proxy.
|
||||||
|
#[inline]
|
||||||
|
pub fn forwarded_for(&self) -> &Vec<&str> {
|
||||||
|
&self.forwarded_for
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List of the user-agent facing interface of the proxies
|
||||||
|
#[inline]
|
||||||
|
pub fn forwarded_by(&self) -> &Vec<&str> {
|
||||||
|
&self.forwarded_by
|
||||||
|
}
|
||||||
|
}
|
@ -55,6 +55,7 @@ mod encoding;
|
|||||||
mod httprequest;
|
mod httprequest;
|
||||||
mod httpresponse;
|
mod httpresponse;
|
||||||
mod payload;
|
mod payload;
|
||||||
|
mod info;
|
||||||
mod route;
|
mod route;
|
||||||
mod resource;
|
mod resource;
|
||||||
mod recognizer;
|
mod recognizer;
|
||||||
@ -81,6 +82,7 @@ pub use error::{Error, Result};
|
|||||||
pub use encoding::ContentEncoding;
|
pub use encoding::ContentEncoding;
|
||||||
pub use body::{Body, Binary};
|
pub use body::{Body, Binary};
|
||||||
pub use application::Application;
|
pub use application::Application;
|
||||||
|
pub use info::ConnectionInfo;
|
||||||
pub use httprequest::{HttpRequest, UrlEncoded};
|
pub use httprequest::{HttpRequest, UrlEncoded};
|
||||||
pub use httpresponse::HttpResponse;
|
pub use httpresponse::HttpResponse;
|
||||||
pub use payload::{Payload, PayloadItem};
|
pub use payload::{Payload, PayloadItem};
|
||||||
|
@ -209,28 +209,17 @@ pub struct RouteRecognizer<T> {
|
|||||||
patterns: HashMap<String, Pattern>,
|
patterns: HashMap<String, Pattern>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for RouteRecognizer<T> {
|
|
||||||
|
|
||||||
fn default() -> Self {
|
|
||||||
RouteRecognizer {
|
|
||||||
prefix: 0,
|
|
||||||
re: RegexSet::new([""].iter()).unwrap(),
|
|
||||||
routes: Vec::new(),
|
|
||||||
patterns: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> RouteRecognizer<T> {
|
impl<T> RouteRecognizer<T> {
|
||||||
|
|
||||||
pub fn new<P: Into<String>, U>(prefix: P, routes: U) -> Self
|
pub fn new<P: Into<String>, U, K>(prefix: P, routes: U) -> Self
|
||||||
where U: IntoIterator<Item=(String, Option<String>, T)>
|
where U: IntoIterator<Item=(K, Option<String>, T)>,
|
||||||
|
K: Into<String>,
|
||||||
{
|
{
|
||||||
let mut paths = Vec::new();
|
let mut paths = Vec::new();
|
||||||
let mut handlers = Vec::new();
|
let mut handlers = Vec::new();
|
||||||
let mut patterns = HashMap::new();
|
let mut patterns = HashMap::new();
|
||||||
for item in routes {
|
for item in routes {
|
||||||
let (pat, elements) = parse(&item.0);
|
let (pat, elements) = parse(&item.0.into());
|
||||||
let pattern = Pattern::new(&pat, elements);
|
let pattern = Pattern::new(&pat, elements);
|
||||||
if let Some(ref name) = item.1 {
|
if let Some(ref name) = item.1 {
|
||||||
let _ = patterns.insert(name.clone(), pattern.clone());
|
let _ = patterns.insert(name.clone(), pattern.clone());
|
||||||
@ -399,8 +388,6 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_recognizer() {
|
fn test_recognizer() {
|
||||||
let mut rec = RouteRecognizer::<usize>::default();
|
|
||||||
|
|
||||||
let routes = vec![
|
let routes = vec![
|
||||||
("/name", None, 1),
|
("/name", None, 1),
|
||||||
("/name/{val}", None, 2),
|
("/name/{val}", None, 2),
|
||||||
@ -408,7 +395,7 @@ mod tests {
|
|||||||
("/v{val}/{val2}/index.html", None, 4),
|
("/v{val}/{val2}/index.html", None, 4),
|
||||||
("/v/{tail:.*}", None, 5),
|
("/v/{tail:.*}", None, 5),
|
||||||
];
|
];
|
||||||
rec.set_routes(routes);
|
let mut rec = RouteRecognizer::new("/", routes);
|
||||||
|
|
||||||
let (params, val) = rec.recognize("/name").unwrap();
|
let (params, val) = rec.recognize("/name").unwrap();
|
||||||
assert_eq!(*val, 1);
|
assert_eq!(*val, 1);
|
||||||
|
@ -66,13 +66,9 @@ use wsframe;
|
|||||||
use wsproto::*;
|
use wsproto::*;
|
||||||
pub use wsproto::CloseCode;
|
pub use wsproto::CloseCode;
|
||||||
|
|
||||||
#[doc(hidden)]
|
|
||||||
const SEC_WEBSOCKET_ACCEPT: &str = "SEC-WEBSOCKET-ACCEPT";
|
const SEC_WEBSOCKET_ACCEPT: &str = "SEC-WEBSOCKET-ACCEPT";
|
||||||
#[doc(hidden)]
|
|
||||||
const SEC_WEBSOCKET_KEY: &str = "SEC-WEBSOCKET-KEY";
|
const SEC_WEBSOCKET_KEY: &str = "SEC-WEBSOCKET-KEY";
|
||||||
#[doc(hidden)]
|
|
||||||
const SEC_WEBSOCKET_VERSION: &str = "SEC-WEBSOCKET-VERSION";
|
const SEC_WEBSOCKET_VERSION: &str = "SEC-WEBSOCKET-VERSION";
|
||||||
// #[doc(hidden)]
|
|
||||||
// const SEC_WEBSOCKET_PROTOCOL: &'static str = "SEC-WEBSOCKET-PROTOCOL";
|
// const SEC_WEBSOCKET_PROTOCOL: &'static str = "SEC-WEBSOCKET-PROTOCOL";
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user