mirror of https://github.com/rwf2/Rocket.git
parent
2f7961f410
commit
c2899b2391
|
@ -1,5 +1,5 @@
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::net::SocketAddr;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
|
||||
|
@ -192,6 +192,34 @@ impl<'r> Request<'r> {
|
|||
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
|
||||
/// the headers in `self`.
|
||||
///
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
use std::str::from_utf8_unchecked;
|
||||
use std::cmp::min;
|
||||
use std::net::SocketAddr;
|
||||
use std::io::{self, Write};
|
||||
use std::mem;
|
||||
|
||||
|
@ -173,26 +172,9 @@ impl Rocket {
|
|||
/// Preprocess the request for Rocket things. Currently, this means:
|
||||
///
|
||||
/// * 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.
|
||||
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
|
||||
// field which we use to reinterpret the request's method.
|
||||
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