///|
/// http11.mbt HTTP Client Example
/// Similar to http11-rs http11_client example
///|
fn bytes_to_array(b : Bytes) -> Array[Byte] {
let arr : Array[Byte] = []
for i in 0.. Bytes {
Bytes::from_array(arr)
}
///|
fn body_to_string(body : Array[Byte]) -> String {
let mut result = ""
for b in body {
result = result + Int::unsafe_to_char(b.to_int()).to_string()
}
result
}
///|
fn string_slice(s : String, start : Int, end : Int) -> String {
let mut result = ""
for i in start.. String {
string_slice(s, start, s.length())
}
///|
/// Parse a simple URL like http://host:port/path
/// Returns (host, port, path)
fn parse_url(url : String) -> (String, Int, String) {
// Remove http:// prefix if present
let mut rest = url
if url.has_prefix("http://") {
rest = string_slice_from(url, 7)
}
// Find path separator
let mut host_port = rest
let mut path = "/"
for i in 0.. Int {
let mut result = 0
for i in 0..= 48 && ci <= 57 {
result = result * 10 + (ci - 48)
} else {
break
}
}
if result == 0 {
80
} else {
result
}
}
///|
fn print_response(response : @lib.Response) -> Unit {
println(
"\{response.version} \{response.status_code} \{response.reason_phrase}",
)
for h in response.headers {
let (name, value) = h
println("\{name}: \{value}")
}
println("")
println("Body length: \{response.body.length()}")
if response.body.length() > 0 {
println(body_to_string(response.body))
}
}
///|
async fn main {
// Default URL - in a real CLI app, this would come from command line args
let url = "http://127.0.0.1:8080/"
println("Fetching \{url}...")
println("")
let (host, port, path) = parse_url(url)
// Build request
let request = @lib.Request::new("GET", path)
.header("Host", host)
.header("User-Agent", "http11.mbt/0.1.0")
.header("Accept", "*/*")
.header("Connection", "close")
let request_bytes = @lib.encode_request(request)
// Connect to server
let addr = @socket.Addr::parse("\{host}:\{port}")
let conn = @socket.Tcp::connect(addr)
// Send request
conn.write(array_to_bytes(request_bytes))
// Receive response
let decoder = @lib.ResponseDecoder::new()
while conn.read_some() is Some(data) {
match decoder.feed(bytes_to_array(data)) {
Err(e) => {
println("Error feeding data: \{e}")
break
}
Ok(_) => ()
}
match decoder.decode() {
Ok(Some(response)) => {
print_response(response)
break
}
Ok(None) | Err(@lib.HttpError::UnexpectedEof) => ()
Err(e) => {
println("Error decoding response: \{e}")
break
}
}
}
conn.close()
}