Last active
December 26, 2015 13:19
-
-
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?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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| { | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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