Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Implement send method to send content along with the request #23

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 36 additions & 6 deletions src/examples/client/client.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use http::method::{Get, Post};
use http::headers::HeaderEnum;
use std::str;
use std::rt::io::extensions::ReaderUtil;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};

fn main() {
let mut request = ~RequestWriter::new(Get, FromStr::from_str("http://localhost/example")
fn get_request() {
let request = ~RequestWriter::new(Get, FromStr::from_str("http://httpbin.org/get")
.expect("Uh oh, that's *really* badly broken!"));
// Temporary measure, as hostname lookup is not yet supported in std::rt::io.
request.remote_addr = Some(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 });

let mut response = match request.read_response() {
Ok(response) => response,
Err(_request) => fail!("This example can progress no further with no response :-("),
};

println("Yay! Started to get the response.");
println!("Status: {}", response.status);
println("Headers:");
Expand All @@ -25,3 +24,34 @@ fn main() {
println("Response:");
println(str::from_utf8(response.read_to_end()));
}


fn post_request() {
let mut request = ~RequestWriter::new(Post, FromStr::from_str("http://httpbin.org/post")
.expect("Uh oh, that's *really* badly broken!"));

request.send(bytes!("Post It!"));

let mut response = match request.read_response() {
Ok(response) => response,
Err(_request) => fail!("This example can progress no further with no response :-("),
};

println("Yay! Started to get the response.");
println!("Status: {}", response.status);
println("Headers:");
for header in response.headers.iter() {
println!(" - {}: {}", header.header_name(), header.header_value());
}

print("\n");
println("Response:");
println(str::from_utf8(response.read_to_end()));
}

fn main() {

get_request();

post_request();
}
33 changes: 30 additions & 3 deletions src/libhttp/client/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,33 @@ impl RequestWriter<TcpStream> {
let s = format!("{} {} HTTP/1.0\r\n", self.method.to_str(), self.url.to_str());
self.stream.write(s.as_bytes());

// `write_all` adds '\r\n' at the end, no
// need to terminate the headers section
// here.
self.headers.write_all(&mut self.stream);
self.headers_written = true;
}

/// Send data to the remote server.
/// This method appends Content-Length
/// to headers and sends them. If headers
/// where already sent, it will send data
/// without the Content-Length.
// TODO: Implement chunked request, perhaps
// in a `send_chunked` method.
pub fn send(&mut self, buf: &[u8]) {

// NOTE: Should we make this fail?
// If 'Content-Length' is not sent
// some servers won't read the request
// body.
if !self.headers_written {
self.headers.content_length = Some(buf.len());
self.write_headers();
}
self.write(buf);
}

// FIXME: ~self rather than self to work around a Rust bug in by-val self at present leading to
// a segfault on calling construct().
pub fn read_response(~self) -> Result<ResponseReader<TcpStream>, ~RequestWriter<TcpStream>> {
Expand All @@ -185,9 +208,13 @@ impl RequestWriter<TcpStream> {

impl Writer for RequestWriter<TcpStream> {
fn write(&mut self, buf: &[u8]) {
if (!self.headers_written) {
self.write_headers();
}
// No data must be sent before
// sending headers. Let's make
// sure that's the case.
self.try_write_headers();

// Now we're good to send
// some data.
self.stream.write(buf);
}

Expand Down