mirror of https://github.com/rwf2/Rocket.git
parent
2f7961f410
commit
c2899b2391
|
@ -1,5 +1,5 @@
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::net::SocketAddr;
|
use std::net::{IpAddr, SocketAddr};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
@ -192,6 +192,34 @@ impl<'r> Request<'r> {
|
||||||
self.remote = Some(address);
|
self.remote = Some(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the ip address "X-Real-IP" header if found.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Get the value of the ip out of the "X-Real-IP" header.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use rocket::Request;
|
||||||
|
/// # use rocket::http::{Header, Method};
|
||||||
|
/// # use std::net::{SocketAddr, IpAddr, Ipv4Addr};
|
||||||
|
///
|
||||||
|
/// # Request::example(Method::Get, "/uri", |mut request| {
|
||||||
|
/// request.add_header(Header::new("X-Real-IP", "8.8.8.8"));
|
||||||
|
/// let ip = request.real_ip().expect("X-Real-IP not set");
|
||||||
|
/// assert_eq!(ip, "8.8.8.8".parse::<Ipv4Addr>().unwrap());
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn real_ip(&self) -> Option<IpAddr> {
|
||||||
|
self.headers()
|
||||||
|
.get_one("X-Real-IP")
|
||||||
|
.and_then(|ip| {
|
||||||
|
ip.parse()
|
||||||
|
.map_err(|_| warn_!("'X-Real-IP' header is malformed: {}", ip))
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a [`HeaderMap`](/rocket/http/struct.HeaderMap.html) of all of
|
/// Returns a [`HeaderMap`](/rocket/http/struct.HeaderMap.html) of all of
|
||||||
/// the headers in `self`.
|
/// the headers in `self`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::str::from_utf8_unchecked;
|
use std::str::from_utf8_unchecked;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
@ -173,26 +172,9 @@ impl Rocket {
|
||||||
/// Preprocess the request for Rocket things. Currently, this means:
|
/// Preprocess the request for Rocket things. Currently, this means:
|
||||||
///
|
///
|
||||||
/// * Rewriting the method in the request if _method form field exists.
|
/// * Rewriting the method in the request if _method form field exists.
|
||||||
/// * Rewriting the remote IP if the 'X-Real-IP' header is set.
|
|
||||||
///
|
///
|
||||||
/// Keep this in-sync with derive_form when preprocessing form fields.
|
/// Keep this in-sync with derive_form when preprocessing form fields.
|
||||||
fn preprocess_request(&self, req: &mut Request, data: &Data) {
|
fn preprocess_request(&self, req: &mut Request, data: &Data) {
|
||||||
// Rewrite the remote IP address. The request must already have an
|
|
||||||
// address associated with it to do this since we need to know the port.
|
|
||||||
if let Some(current) = req.remote() {
|
|
||||||
let ip = req.headers()
|
|
||||||
.get_one("X-Real-IP")
|
|
||||||
.and_then(|ip| {
|
|
||||||
ip.parse()
|
|
||||||
.map_err(|_| warn_!("'X-Real-IP' header is malformed: {}", ip))
|
|
||||||
.ok()
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(ip) = ip {
|
|
||||||
req.set_remote(SocketAddr::new(ip, current.port()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if this is a form and if the form contains the special _method
|
// Check if this is a form and if the form contains the special _method
|
||||||
// field which we use to reinterpret the request's method.
|
// field which we use to reinterpret the request's method.
|
||||||
let data_len = data.peek().len();
|
let data_len = data.peek().len();
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
#![feature(plugin, decl_macro, custom_derive)]
|
|
||||||
#![plugin(rocket_codegen)]
|
|
||||||
|
|
||||||
extern crate rocket;
|
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[get("/")]
|
|
||||||
fn get_ip(remote: SocketAddr) -> String {
|
|
||||||
remote.to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
mod remote_rewrite_tests {
|
|
||||||
use super::*;
|
|
||||||
use rocket::local::Client;
|
|
||||||
use rocket::http::{Header, Status};
|
|
||||||
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
const KNOWN_IP: &'static str = "127.0.0.1:8000";
|
|
||||||
|
|
||||||
fn check_ip(header: Option<Header<'static>>, ip: Option<String>) {
|
|
||||||
let addr: SocketAddr = KNOWN_IP.parse().unwrap();
|
|
||||||
|
|
||||||
let c = Client::new(rocket::ignite().mount("/", routes![get_ip])).unwrap();
|
|
||||||
let mut response = match header {
|
|
||||||
Some(header) => c.get("/").header(header).remote(addr).dispatch(),
|
|
||||||
None => c.get("/").remote(addr).dispatch()
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(response.status(), Status::Ok);
|
|
||||||
let body = response.body_string();
|
|
||||||
match ip {
|
|
||||||
Some(ip) => assert_eq!(body, Some(format!("{}:{}", ip, addr.port()))),
|
|
||||||
None => assert_eq!(body, Some(KNOWN_IP.into()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x_real_ip_rewrites() {
|
|
||||||
let ip = "8.8.8.8";
|
|
||||||
check_ip(Some(Header::new("X-Real-IP", ip)), Some(ip.to_string()));
|
|
||||||
|
|
||||||
let ip = "129.120.111.200";
|
|
||||||
check_ip(Some(Header::new("X-Real-IP", ip)), Some(ip.to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn x_real_ip_rewrites_ipv6() {
|
|
||||||
let ip = "2001:db8:0:1:1:1:1:1";
|
|
||||||
check_ip(Some(Header::new("X-Real-IP", ip)), Some(format!("[{}]", ip)));
|
|
||||||
|
|
||||||
let ip = "2001:db8::2:1";
|
|
||||||
check_ip(Some(Header::new("X-Real-IP", ip)), Some(format!("[{}]", ip)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn uncased_header_rewrites() {
|
|
||||||
let ip = "8.8.8.8";
|
|
||||||
check_ip(Some(Header::new("x-REAL-ip", ip)), Some(ip.to_string()));
|
|
||||||
|
|
||||||
let ip = "1.2.3.4";
|
|
||||||
check_ip(Some(Header::new("x-real-ip", ip)), Some(ip.to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_header_no_rewrite() {
|
|
||||||
check_ip(Some(Header::new("real-ip", "?")), None);
|
|
||||||
check_ip(None, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bad_header_doesnt_rewrite() {
|
|
||||||
let ip = "092348092348";
|
|
||||||
check_ip(Some(Header::new("X-Real-IP", ip)), None);
|
|
||||||
|
|
||||||
let ip = "1200:100000:0120129";
|
|
||||||
check_ip(Some(Header::new("X-Real-IP", ip)), None);
|
|
||||||
|
|
||||||
let ip = "192.168.1.900";
|
|
||||||
check_ip(Some(Header::new("X-Real-IP", ip)), None);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue