Skip to content

Instantly share code, notes, and snippets.

@bickfordb
Last active December 26, 2015 13:19
Show Gist options
  • Select an option

  • Save bickfordb/7157675 to your computer and use it in GitHub Desktop.

Select an option

Save bickfordb/7157675 to your computer and use it in GitHub Desktop.
I'm trying to write a small HTTP server in Rust. What am I doing wrong?
use std::cell::Cell;
//use std::rt::io::{Writer};
use std::rt::io::{Reader};
use std::rt::io::{Acceptor};
use std::rt::io::{Listener};
use std::rt::io::buffered::{BufferedReader,BufferedStream};
use std::rt::io::net::tcp::{TcpListener, TcpStream};
type Header = (~str, ~str);
struct Request {
method: ~str,
protocol: ~str,
uri: ~str,
stream: TcpStream,
headers: ~[Header]
}
impl Request {
fn new(stream: TcpStream) -> Request {
let req = Request{
method: ~"",
uri: ~"",
protocol: ~"",
stream: stream,
headers: ~[]
};
return req;
}
fn read_up_to(&mut self, terminator: u8) -> Option<~str> {
let mut x = ~[];
let mut buf = [0u8];
loop {
match self.stream.read(buf) {
None => { return None; },
Some(n) => {
if n > 0 {
x.push_all(buf);
if buf[0] == terminator {
break;
}
}
}
}
}
return Some(std::str::from_utf8_owned(x));
}
fn read_line(&mut self) -> Option<~str> {
return self.read_up_to('\n' as u8);
}
fn read_request_line(&mut self) -> bool {
match self.read_line() {
None => {
return false;
},
Some(line) => {
let mut i = 0;
for word in line.word_iter() {
let s : ~str = word.into_owned();
if i == 0 {
self.method = s;
} else if i == 1 {
self.uri = s;
} else if i == 2 {
self.protocol = s;
return true;
}
i += 1;
}
}
}
return false;
}
fn read_headers(&mut self) -> bool {
loop {
match self.read_line() {
Some(~"\r\n") => { break; }
Some(line) => {
let line = line.trim();
let mut i = 0;
let mut key = ~"";
let mut value = ~"";
for term in line.trim().splitn_iter(':', 1) {
let term = term.trim().into_owned();
if i == 0 {
key = term;
} else {
value = term;
}
i += 1;
}
println("key: " + key + " value: " + value);
self.headers.push((key, value));
println("got header: " + line);
},
None => { return false }
}
}
return true;
}
fn read(&mut self) -> bool {
if !self.read_request_line() {
return false;
}
if !self.read_headers() {
return false;
}
return true;
}
}
struct ResponseWriter {
isStarted: bool,
headers: ~[Header]
}
impl ResponseWriter {
fn new() -> ResponseWriter {
ResponseWriter {
isStarted: false,
headers: ~[]
}
}
fn writeHeader(status: int) {
let message = toStatusMessage(status);
let mut buf : ~[u8] = ~[];
}
}
fn toStatusMessage(code: int) -> ~str {
match code {
200 => ~"OK",
301 => ~"Moved Permanently",
302 => ~"Found",
303 => ~"See Other",
304 => ~"Not Modified",
307 => ~"Temporary Redirect",
400 => ~"Bad Request",
404 => ~"Not Found",
500 => ~"Internal Server Error",
_ => ~"Unknown"
}
}
fn serve(addr: ~str, handler: ~fn(~Request, ~ResponseWriter)) {
match from_str("127.0.0.1:9393") {
Some(addr) => {
match TcpListener::bind(addr).listen() {
None => println("failed to create listener"),
Some(listener) => {
let mut listener0 = listener;
loop {
match listener0.accept() {
Some(stream) => {
let cell = Cell::new(stream);
let handlerCell = Cell::new(handler);
do spawn {
let stream0 = cell.take();
let handler0 = handlerCell.take();
let mut request = ~Request::new(stream0);
let mut responseWriter = ~ResponseWriter::new();
if request.read() {
handler0(request, responseWriter);
}
}
},
None => ()
}
}
}
}
}
None => println("failed to parse address: " + addr)
}
}
fn main() {
struct Q;
do serve(~"127.0.0.1:9393") |req, resp| {
}
}
http2.rs:163:44: 163:51 error: use of moved value: `handler`
http2.rs:163 let handlerCell = Cell::new(handler);
^~~~~~~
http2.rs:163:44: 163:51 note: `handler` moved here because it has type `~fn:Send(~Request, ~ResponseWriter)`, which is non-copyable (perhaps you meant to use clone()?)
http2.rs:163 let handlerCell = Cell::new(handler);
^~~~~~~
error: aborting due to previous error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment