1 | 1 |
extern crate hyper;
|
2 | 2 |
|
3 | |
// use std::io::Write;
|
4 | |
|
5 | 3 |
use hyper::Server;
|
6 | |
use hyper::server::{Request,Response};
|
| 4 |
use hyper::server::{Handler,Request,Response};
|
7 | 5 |
use hyper::net::Fresh;
|
8 | 6 |
|
9 | |
#[derive(Debug, Clone)]
|
10 | |
struct Delegate {
|
11 | |
name: String,
|
| 7 |
use std::env::{args,current_dir,set_current_dir};
|
| 8 |
use std::fs::{File,read_dir};
|
| 9 |
use std::io::prelude::Read;
|
| 10 |
use std::iter::Iterator;
|
| 11 |
use std::path::Path;
|
| 12 |
|
| 13 |
mod matching;
|
| 14 |
|
| 15 |
#[derive(Debug)]
|
| 16 |
enum AloysError {
|
| 17 |
IOError(std::io::Error),
|
| 18 |
HyperError(hyper::error::Error),
|
| 19 |
}
|
| 20 |
|
| 21 |
impl From<std::io::Error> for AloysError {
|
| 22 |
fn from(e: std::io::Error) -> AloysError {
|
| 23 |
AloysError::IOError(e)
|
| 24 |
}
|
| 25 |
}
|
| 26 |
|
| 27 |
impl From<hyper::error::Error> for AloysError {
|
| 28 |
fn from(e: hyper::error::Error) -> AloysError {
|
| 29 |
AloysError::HyperError(e)
|
| 30 |
}
|
12 | 31 |
}
|
13 | 32 |
|
14 | 33 |
#[derive(Debug, Clone)]
|
15 | |
struct PathSpec {
|
16 | |
forPath: Option<String>,
|
17 | |
forDomain: Option<String>,
|
18 | |
delegateTo: Delegate,
|
| 34 |
enum Delegate {
|
| 35 |
Forward(HTTPForward),
|
| 36 |
Defer(Routes),
|
19 | 37 |
}
|
20 | 38 |
|
21 | |
fn find_delegate(req: Request, delegates: Vec<PathSpec>) -> Option<Delegate> {
|
22 | |
for d in delegates.iter() {
|
23 | |
if let Some(ref domain) = d.forDomain {
|
24 | |
}
|
25 | |
if let Some(ref path) = d.forPath {
|
| 39 |
#[derive(Debug, Clone)]
|
| 40 |
struct HTTPForward {
|
| 41 |
domn: String,
|
| 42 |
port: u32,
|
| 43 |
}
|
| 44 |
|
| 45 |
#[derive(Debug, Clone)]
|
| 46 |
struct RouteSpec {
|
| 47 |
for_path: Option<String>,
|
| 48 |
for_domain: Option<String>,
|
| 49 |
delegate_to: Delegate,
|
| 50 |
}
|
| 51 |
|
| 52 |
#[derive(Debug, Clone)]
|
| 53 |
struct Routes {
|
| 54 |
routes: Vec<RouteSpec>,
|
| 55 |
}
|
| 56 |
|
| 57 |
fn with_file_contents<A, F>(path: &Path, default: A, callback: F) -> A
|
| 58 |
where F: FnOnce(String) -> A + 'static {
|
| 59 |
match File::open(path) {
|
| 60 |
Ok(mut f) => {
|
| 61 |
let mut s = String::new();
|
| 62 |
match f.read_to_string(&mut s) {
|
| 63 |
Ok(_) => callback(s),
|
| 64 |
Err(_) => default,
|
| 65 |
}
|
| 66 |
},
|
| 67 |
Err(_) => default,
|
| 68 |
}
|
| 69 |
}
|
| 70 |
|
| 71 |
impl RouteSpec {
|
| 72 |
fn from_path(dir: &Path) -> Result<RouteSpec,AloysError> {
|
| 73 |
let path = with_file_contents(&dir.join("path"), None, |s| Some(s));
|
| 74 |
let domain = with_file_contents(&dir.join("domain"), None, |s| Some(s));
|
| 75 |
let mode = with_file_contents(&dir.join("mode"), "http", |s| s);
|
| 76 |
if mode == "http" {
|
| 77 |
} else if mode == "alyos" {
|
| 78 |
let fwd = with_file_contents(&dir.join("conf"),
|
| 79 |
Path::new(&"/dev/null"),
|
| 80 |
|s| Path::new(&s));
|
| 81 |
let rts = try!(Routes::load_paths(fwd));
|
| 82 |
Ok(RouteSpec { for_path: path,
|
| 83 |
for_domain: domain,
|
| 84 |
delegate_to: Delegate::
|
| 85 |
} else {
|
26 | 86 |
|
27 | 87 |
}
|
28 | |
return Some(d.delegateTo.clone());
|
| 88 |
// let forPath = match File::open(dir.join("path")) {
|
| 89 |
// Ok(f) => {};
|
| 90 |
// Err
|
| 91 |
// };
|
| 92 |
Ok(RouteSpec { for_path: None,
|
| 93 |
for_domain: None,
|
| 94 |
delegate_to: Delegate::Defer(Routes { routes: vec![] }),
|
| 95 |
})
|
29 | 96 |
}
|
30 | |
return None;
|
31 | 97 |
}
|
32 | 98 |
|
33 | |
fn dispatch(req: Request, res: Response<Fresh>, delegates: Vec<PathSpec>) {
|
34 | |
println!("{:?}", req.headers);
|
35 | |
res.send(b"Unhandled request.").unwrap();
|
| 99 |
impl Routes {
|
| 100 |
fn load_paths(dir: &Path) -> Result<Routes,AloysError> {
|
| 101 |
let mut routes = vec![];
|
| 102 |
for entry in try!(read_dir(dir)) {
|
| 103 |
let entry_path = try!(entry).path();
|
| 104 |
routes.push(try!(RouteSpec::from_path(entry_path.as_path())));
|
| 105 |
}
|
| 106 |
Ok(Routes { routes: routes })
|
| 107 |
}
|
| 108 |
|
| 109 |
fn dispatch(&self, req: &Request, res: Response<Fresh>) {
|
| 110 |
match self.find_delegate(&req) {
|
| 111 |
Some(delegate) => delegate.run(req, res),
|
| 112 |
None => {
|
| 113 |
let _ = res.send(b"[no matching handler]");
|
| 114 |
},
|
| 115 |
}
|
| 116 |
}
|
| 117 |
|
| 118 |
fn find_delegate(&self, req: &Request) -> Option<&Delegate> {
|
| 119 |
for d in self.routes.iter() {
|
| 120 |
if let Some(ref d) = d.for_domain {
|
| 121 |
println!("Matching against {:?}", d);
|
| 122 |
}
|
| 123 |
if let Some(ref p) = d.for_path {
|
| 124 |
println!("Matching against {:?}", p);
|
| 125 |
}
|
| 126 |
return Some(&d.delegate_to);
|
| 127 |
}
|
| 128 |
return None;
|
| 129 |
}
|
36 | 130 |
}
|
37 | 131 |
|
38 | |
fn hello(req: Request, res: Response<Fresh>) {
|
39 | |
res.send(b"Unhandled request.").unwrap();
|
| 132 |
impl Handler for Routes {
|
| 133 |
fn handle(&self, req: Request, res: Response<Fresh>) {
|
| 134 |
self.dispatch(&req, res);
|
| 135 |
}
|
| 136 |
}
|
| 137 |
|
| 138 |
impl Delegate {
|
| 139 |
fn run(&self, req: &Request, res: Response<Fresh>) {
|
| 140 |
match self {
|
| 141 |
&Delegate::Forward(_) => {
|
| 142 |
let _ = res.send(b"[matched by me!]");
|
| 143 |
},
|
| 144 |
&Delegate::Defer(ref rts) => {
|
| 145 |
rts.dispatch(req, res);
|
| 146 |
},
|
| 147 |
}
|
| 148 |
}
|
| 149 |
}
|
| 150 |
|
| 151 |
|
| 152 |
fn run_server() -> Result<(), AloysError> {
|
| 153 |
if let Some(target_dir) = args().next() {
|
| 154 |
println!("switching to directory {:}", target_dir);
|
| 155 |
try!(set_current_dir(Path::new(&target_dir)));
|
| 156 |
}
|
| 157 |
let cwd = try!(current_dir());
|
| 158 |
let paths = try!(Routes::load_paths(cwd.as_path()));
|
| 159 |
let srv = try!(Server::http("127.0.0.1:8080"));
|
| 160 |
let _ = srv.handle(paths);
|
| 161 |
Ok(())
|
40 | 162 |
}
|
41 | 163 |
|
42 | 164 |
fn main() {
|
43 | |
let sample: Vec<PathSpec> = vec![
|
44 | |
PathSpec { forPath: None,
|
45 | |
forDomain: None,
|
46 | |
delegateTo: Delegate { name: "default".to_owned() } } ];
|
47 | |
match Server::http("127.0.0.1:8080") {
|
48 | |
Ok(s) => {
|
49 | |
let _ = s.handle(hello);
|
50 | |
}
|
51 | |
Err(e) => {
|
52 | |
println!("Unable to run server: {:?}", e);
|
53 | |
}
|
54 | |
}
|
| 165 |
match run_server() {
|
| 166 |
Ok(_) => (),
|
| 167 |
Err(e) => println!("Got error: {:?}", e),
|
| 168 |
};
|
55 | 169 |
}
|