Skip to content

Commit

Permalink
refactor and document request module
Browse files Browse the repository at this point in the history
  • Loading branch information
jayjamesjay committed Jun 24, 2024
1 parent 038f10d commit 666c218
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 197 deletions.
12 changes: 12 additions & 0 deletions examples/chunked.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use http_req::request;

fn main() {
//Sends a HTTP GET request and processes the response.
let mut body = Vec::new();
let res = request::get("https://jigsaw.w3.org/HTTP/ChunkedScript", &mut body).unwrap();

//Prints details about the response.
println!("Status: {} {}", res.status_code(), res.reason());
println!("Headers: {}", res.headers());
//println!("{}", String::from_utf8_lossy(&body));
}
58 changes: 34 additions & 24 deletions examples/request_builder_get.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,53 @@
use http_req::{
request::RequestBuilder,
response::{find_slice, Response},
stream::Stream,
uri::Uri,
};
use http_req::{request::RequestBuilder, response::Response, stream::Stream, uri::Uri};
use std::{
convert::TryFrom,
io::{Read, Write},
io::{BufRead, BufReader, Read, Write},
time::Duration,
};

fn main() {
//Parses a URI and assigns it to a variable `addr`.
let addr: Uri = Uri::try_from("https://www.rust-lang.org/learn").unwrap();

//Prepare a request
let mut request_builder = RequestBuilder::new(&addr);
request_builder.header("Connection", "Close");
//Containers for a server's response.
let mut raw_head = Vec::new();
let mut body = Vec::new();

//Prepares a request message.
let request_msg = RequestBuilder::new(&addr)
.header("Connection", "Close")
.parse();

//Container for a server's response.
let mut writer = Vec::new();
println!("{:?}", String::from_utf8(request_msg.clone()));

//Connects to a remote host. Uses information from `addr`.
//Connects to a server. Uses information from `addr`.
let mut stream = Stream::new(&addr, Some(Duration::from_secs(60))).unwrap();
stream = Stream::try_to_https(stream, &addr, None).unwrap();

//Generate a request (message) and send it to server.
let request_msg = request_builder.parse_msg();
//Makes a request to server - sends a prepared message.
stream.write_all(&request_msg).unwrap();

//Read response from the server and save it to writer
stream.read_to_end(&mut writer).unwrap();

//Parse and process response.
let pos = find_slice(&writer, &[13, 10, 13, 10].to_owned()).unwrap();
let response = Response::from_head(&writer[..pos]).unwrap();
let body = writer[pos..].to_vec();

//Print infromation about the response.
//Wraps the stream in BufReader to make it easier to read from it.
//Reads a response from the server and saves the head to `raw_head`, and the body to `body`.
let mut stream = BufReader::new(stream);
loop {
match stream.read_until(0xA, &mut raw_head) {
Ok(0) | Err(_) => break,
Ok(len) => {
let full_len = raw_head.len();

if len == 2 && &raw_head[full_len - 2..] == b"\r\n" {
break;
}
}
}
}
stream.read_to_end(&mut body).unwrap();

//Parses and processes the response.
let response = Response::from_head(&raw_head).unwrap();

//Prints infromation about the response.
println!("Status: {} {}", response.status_code(), response.reason());
println!("Headers: {}", response.headers());
//println!("{}", String::from_utf8_lossy(&body));
Expand Down
49 changes: 36 additions & 13 deletions src/chunked.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
//! module chunked implements the wire protocol for HTTP's "chunked" Transfer-Encoding.
//! And it's a rust version of the reference implementation in [Go][1].
//!
//! [1]: https://golang.google.cn/src/net/http/internal/chunked.go
//!
//!implements the wire protocol for HTTP's "chunked" Transfer-Encoding.
///
///It's a Rust version of the reference implementation in [Go][1].
///
///[1]: https://golang.google.cn/src/net/http/internal/chunked.go
///

use std::io::{self, BufRead, BufReader, Error, ErrorKind, Read};

const MAX_LINE_LENGTH: usize = 4096;
const CR_LF: [u8; 2] = [b'\r', b'\n'];

pub struct Reader<R> {
pub struct ChunkReader<R> {
check_end: bool,
eof: bool,
err: Option<Error>,
n: usize,
reader: BufReader<R>,
}

impl<R> Read for Reader<R>
impl<R> Read for ChunkReader<R>
where
R: Read,
{
Expand Down Expand Up @@ -93,7 +94,29 @@ where
}
}

impl<R> Reader<R>
impl<R: Read> BufRead for ChunkReader<R> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
self.reader.fill_buf()
}

fn consume(&mut self, amt: usize) {
self.reader.consume(amt)
}
}

impl<R: Read> From<BufReader<R>> for ChunkReader<R> {
fn from(value: BufReader<R>) -> Self {
ChunkReader {
check_end: false,
eof: false,
err: None,
n: 0,
reader: value,
}
}
}

impl<R> ChunkReader<R>
where
R: Read,
{
Expand Down Expand Up @@ -216,7 +239,7 @@ mod tests {
#[test]
fn read() {
let data: &[u8] = b"7\r\nhello, \r\n17\r\nworld! 0123456789abcdef\r\n0\r\n";
let mut reader = Reader::new(data);
let mut reader = ChunkReader::new(data);
let mut writer = vec![];
io::copy(&mut reader, &mut writer).expect("failed to dechunk");

Expand All @@ -226,7 +249,7 @@ mod tests {
fn read_multiple() {
{
let data: &[u8] = b"3\r\nfoo\r\n3\r\nbar\r\n0\r\n";
let mut reader = Reader::new(data);
let mut reader = ChunkReader::new(data);
let mut writer = vec![0u8; 10];
let n = reader.read(&mut writer).expect("unexpect error");

Expand All @@ -235,7 +258,7 @@ mod tests {
}
{
let data: &[u8] = b"3\r\nfoo\r\n0\r\n";
let mut reader = Reader::new(data);
let mut reader = ChunkReader::new(data);
let mut writer = vec![0u8; 3];
let n = reader.read(&mut writer).expect("unexpect error");

Expand All @@ -246,7 +269,7 @@ mod tests {
#[test]
fn read_partial() {
let data: &[u8] = b"7\r\n1234567";
let mut reader = Reader::new(data);
let mut reader = ChunkReader::new(data);
let mut writer = vec![];
io::copy(&mut reader, &mut writer).expect("failed to dechunk");

Expand All @@ -260,7 +283,7 @@ mod tests {
+ "world! 0123456789abcdef\r\n"
+ "0;someextension=sometoken\r\n";
let data = data_str.as_bytes();
let mut reader = Reader::new(data);
let mut reader = ChunkReader::new(data);
let mut writer = vec![];

reader.read_to_end(&mut writer).expect("failed to dechunk");
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
//! println!("Status: {} {}", res.status_code(), res.reason());
//!}
//!```
pub mod error;
pub mod uri;
pub mod request;
pub mod response;
pub mod stream;
pub mod chunked;
pub mod tls;
pub mod uri;

mod chunked;
pub mod error;
Loading

0 comments on commit 666c218

Please sign in to comment.