Skip to content

Instantly share code, notes, and snippets.

@wycats
Created June 17, 2014 04:08
Show Gist options
  • Save wycats/8b30f3bf51a44ab45a82 to your computer and use it in GitHub Desktop.
Save wycats/8b30f3bf51a44ab45a82 to your computer and use it in GitHub Desktop.
#![feature(macro_rules)]
extern crate civet;
use std::io::{IoResult,ChanReader,ChanWriter,Reader};
use std::collections::HashMap;
use civet::{Config,Server,Request,Response};
macro_rules! http_write(
($dst:expr, $fmt:expr $($arg:tt)*) => (
let _ = write!($dst, concat!($fmt, "\r\n") $($arg)*);
)
)
fn main() {
let _a = Server::start(Config { port: 8888, threads: 50 }, handler);
loop {
std::io::timer::sleep(1000);
}
}
fn handler(request: &mut Request) -> IoResult<Response<int, ChanReader>> {
let (sender, receiver) = channel();
// copy the request out of the pointer so it can be sent across
// the channel.
let req = request.copy();
let (mut origin, reader) = sendable_reader(request);
spawn(proc() {
let mut res = ChanWriter::new(sender);
let mut reader = reader;
http_write!(res, "<style>body \\{ font-family: sans-serif; \\}</style>");
http_write!(res, "<p>Method: {}</p>", req.method);
http_write!(res, "<p>URL: {}</p>", req.url);
http_write!(res, "<p>HTTP: {}</p>", req.http_version);
http_write!(res, "<p>Remote IP: {}</p>", req.remote_ip);
http_write!(res, "<p>Remote Port: {}</p>", req.remote_port);
http_write!(res, "<p>Remote User: {}</p>", req.remote_user);
http_write!(res, "<p>Query String: {}</p>", req.query_string);
http_write!(res, "<p>SSL?: {}</p>", req.is_ssl);
http_write!(res, "<p>Body: {}</p>", reader.read_to_str());
http_write!(res, "<p>User Agent: {}</p>", req.headers.find_equiv(&"User-Agent"));
http_write!(res, "<h2>Headers</h2><ul>");
for (key, value) in req.headers.iter() {
http_write!(res, "<li>{} = {}</li>", key, value);
}
http_write!(res, "</ul>");
});
origin.block();
let body = ChanReader::new(receiver);
let mut headers = HashMap::new();
headers.insert("Content-Type".to_str(), "text/html".to_str());
Ok(Response::new(200, headers, body))
}
struct ReadProxy {
reader: ChanReader,
control: Sender<int>
}
impl ReadProxy {
fn new(reader: ChanReader, control: Sender<int>) -> ReadProxy {
ReadProxy { reader: reader, control: control }
}
}
impl Reader for ReadProxy {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
self.control.send(buf.len() as int);
self.reader.read(buf)
}
}
struct ReadSender<'a, T> {
reader: &'a mut T,
writer: ChanWriter,
control: Receiver<int>
}
impl<'a, T: Reader> ReadSender<'a, T> {
fn new<'b>(reader: &'b mut T, writer: ChanWriter, control: Receiver<int>) -> ReadSender<'b, T> {
ReadSender {
reader: reader,
writer: writer,
control: control
}
}
fn block(&mut self) -> IoResult<()> {
for len in self.control.iter() {
if len == -1 {
return Ok(());
}
let mut buf = Vec::from_elem(len as uint, 0 as u8);
try!(self.reader.read(buf.as_mut_slice()));
try!(self.writer.write(buf.as_slice()));
}
Ok(())
}
}
fn sendable_reader<'a, R: Reader>(reader: &'a mut R) -> (ReadSender<'a, R>, ReadProxy) {
let (control_sender, control_receiver) = channel();
let (bytes_sender, bytes_receiver) = channel();
let sender = ChanWriter::new(bytes_sender);
let receiver = ChanReader::new(bytes_receiver);
let proxy = ReadProxy::new(receiver, control_sender);
let read_sender = ReadSender::new(reader, sender, control_receiver);
(read_sender, proxy)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment