Skip to content

Commit dadcca0

Browse files
committed
Designing the API chris-morgan#9
1 parent b8eaa86 commit dadcca0

File tree

5 files changed

+158
-18
lines changed

5 files changed

+158
-18
lines changed

src/examples/client/main.rs

+50-11
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,90 @@
11
extern mod http;
22
use http::client::RequestWriter;
3+
use http::client::ResponseReader;
34
use http::method::Get;
45
use http::headers::HeaderEnum;
56
use std::os;
67
use std::str;
78
use std::io::Reader;
9+
use std::io::net::tcp::TcpStream;
10+
11+
// API Examples
12+
use http::client::api::{get, RequestArgs};
813

914
fn main() {
1015
format!("{}", Get);
1116
let args = os::args();
1217
match args.len() {
1318
0 => unreachable!(),
14-
2 => make_and_print_request(args[1]),
19+
2 => get_example(args[1]),
1520
_ => {
1621
println!("Usage: {} URL", args[0]);
1722
return;
1823
},
1924
};
2025
}
2126

22-
fn make_and_print_request(url: ~str) {
23-
let request = RequestWriter::new(Get, from_str(url).expect("Invalid URL :-("));
24-
27+
// NOTE(flaper87): Consider moving this to the
28+
// request sender and print it if built in debug
29+
// mode.
30+
fn debug_request(request: &RequestWriter<TcpStream>) {
2531
println("Request");
2632
println("=======");
2733
println("");
2834
println!("URL: {}", request.url.to_str());
2935
println!("Remote address: {:?}", request.remote_addr);
3036
println!("Method: {}", request.method);
3137
println("Headers:");
32-
for header in request.headers.iter() {
33-
println!(" - {}: {}", header.header_name(), header.header_value());
34-
}
38+
}
3539

40+
// NOTE(flaper87): Consider moving this to the
41+
// request sender and print it if built in debug
42+
// mode.
43+
fn debug_response(response: &ResponseReader<TcpStream>) {
3644
println("");
3745
println("Response");
3846
println("========");
3947
println("");
40-
let mut response = match request.read_response() {
41-
Ok(response) => response,
42-
Err(_request) => fail!("This example can progress no further with no response :-("),
43-
};
4448
println!("Status: {}", response.status);
4549
println("Headers:");
4650
for header in response.headers.iter() {
4751
println!(" - {}: {}", header.header_name(), header.header_value());
4852
}
53+
}
54+
55+
fn get_example(url: ~str) {
56+
let params = ~[(~"test", ~"value")];
57+
let args = RequestArgs{params: Some(params), headers: None, data: None};
58+
let response = get(url, Some(args));
59+
60+
let mut response = match response {
61+
Ok(response) => response,
62+
Err(_request) => fail!("This example can progress no further with no response :-("),
63+
};
64+
65+
debug_response(&response);
66+
67+
print("\n");
68+
println("Response:");
69+
let body = response.read_to_end();
70+
println(str::from_utf8_slice(body));
71+
}
72+
73+
fn make_and_print_request(url: ~str) {
74+
let request = RequestWriter::new(Get, from_str(url).expect("Invalid URL :-("));
75+
76+
debug_request(&request);
77+
for header in request.headers.iter() {
78+
println!(" - {}: {}", header.header_name(), header.header_value());
79+
}
80+
81+
let mut response = match request.read_response() {
82+
Ok(response) => response,
83+
Err(_request) => fail!("This example can progress no further with no response :-("),
84+
};
85+
86+
debug_response(&response);
87+
4988
println("Body:");
5089
let body = response.read_to_end();
5190
println(str::from_utf8_slice(body));

src/http/client/api.rs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use std::default::Default;
2+
use std::io::net::tcp::TcpStream;
3+
4+
use method;
5+
use headers::request::HeaderCollection;
6+
7+
use client::request::RequestWriter;
8+
use client::response::ResponseReader;
9+
use extra::url::{Url, Query};
10+
11+
pub struct RequestArgs {
12+
13+
// Request data
14+
data: Option<~[u8]>,
15+
16+
// Query Parameters
17+
params: Option<Query>,
18+
19+
// Request Headers
20+
headers: Option<~HeaderCollection>,
21+
}
22+
23+
impl Default for RequestArgs {
24+
25+
fn default() -> RequestArgs {
26+
RequestArgs{data: None, params: None, headers: None}
27+
}
28+
}
29+
30+
// Need a fix for https://github.com/mozilla/rust/issues/9056
31+
// before we can use this.
32+
//pub static DEFAULT_ARGS: RequestArgs = RequestArgs{params: None,
33+
// headers: None};
34+
35+
// TODO: Implement a Response trait
36+
37+
pub fn request(method: method::Method, url: ~str, args: Option<RequestArgs>)
38+
-> Result<ResponseReader<TcpStream>, RequestWriter<TcpStream>>{
39+
40+
let default = args.unwrap_or_default();
41+
42+
// Push all query params to the URL.
43+
let mut url: Url = FromStr::from_str(url).expect("Uh oh, that's *really* badly broken!");
44+
45+
if default.params.is_some() {
46+
url.query.push_all(*(default.params.get_ref()));
47+
}
48+
49+
// At this point, we're ready to finally send
50+
// the request. First thing is to write headers,
51+
// then the request data and later get the response
52+
// from the server.
53+
let mut request = RequestWriter::new(method, url);
54+
55+
// Write data if there's some
56+
if default.data.is_some() {
57+
request.send(*(default.data.get_ref()));
58+
}
59+
60+
// This will flush the request's
61+
// stream and get the response from
62+
// the server.
63+
request.read_response()
64+
}
65+
66+
pub fn get(url: ~str, args: Option<RequestArgs>)
67+
-> Result<ResponseReader<TcpStream>, RequestWriter<TcpStream>> {
68+
69+
request(method::Get, url, args)
70+
}
71+
72+
pub fn post(url: ~str, args: Option<RequestArgs>)
73+
-> Result<ResponseReader<TcpStream>, RequestWriter<TcpStream>> {
74+
75+
request(method::Post, url, args)
76+
}
77+
78+
pub fn patch(url: ~str, args: Option<RequestArgs>)
79+
-> Result<ResponseReader<TcpStream>, RequestWriter<TcpStream>> {
80+
81+
request(method::Patch, url, args)
82+
}
83+
84+
pub fn put(url: ~str, args: Option<RequestArgs>)
85+
-> Result<ResponseReader<TcpStream>, RequestWriter<TcpStream>> {
86+
87+
request(method::Put, url, args)
88+
}
89+
90+
pub fn delete(url: ~str, args: Option<RequestArgs>)
91+
-> Result<ResponseReader<TcpStream>, RequestWriter<TcpStream>> {
92+
93+
request(method::Delete, url, args)
94+
}

src/http/client/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ possible, but it's not elegant convenient yet. (Most notably, no transfer-encodi
1818
pub use self::request::RequestWriter;
1919
pub use self::response::ResponseReader;
2020

21+
pub mod api;
2122
pub mod request;
2223
pub mod response;

src/http/client/request.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,15 @@ impl RequestWriter<TcpStream> {
228228
}
229229
}
230230

231-
/// Send data to the remote server.
232-
/// This method appends Content-Length
233-
/// to headers and sends them. If headers
234-
/// where already sent, it will send data
235-
/// without the Content-Length.
236-
// TODO: Implement chunked request, perhaps
237-
// in a `send_chunked` method.
231+
/**
232+
* Send data to the remote server.
233+
* This method appends Content-Length
234+
* to headers and sends them. If headers
235+
* where already sent, it will send data
236+
* without the Content-Length.
237+
* TODO: Implement chunked request, perhaps
238+
* in a `send_chunked` method.
239+
*/
238240
pub fn send(&mut self, buf: &[u8]) {
239241

240242
// NOTE: Should we make this fail?

src/http/client/response.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ impl<S: Stream> ResponseReader<S> {
140140
headers: headers,
141141
})
142142
}
143+
144+
pub fn get_content(&mut self) -> ~[u8] {
145+
self.stream.read_to_end()
146+
}
143147
}
144148

145149
impl<S: Stream> Reader for ResponseReader<S> {

0 commit comments

Comments
 (0)