hydro_test/external_client/
http_hello.rs1use hydro_lang::keyed_singleton::{BoundedValue, KeyedSingleton};
2use hydro_lang::keyed_stream::KeyedStream;
3use hydro_lang::*;
4
5pub fn http_hello_server<'a, P>(
6 in_stream: KeyedStream<u64, String, Process<'a, P>, Unbounded, TotalOrder>,
7) -> KeyedSingleton<u64, String, Process<'a, P>, BoundedValue> {
8 in_stream
9 .inspect_with_key(q!(|(id, line)| println!(
10 "Received line from client #{}: '{}'",
11 id, line
12 )))
13 .fold_early_stop(
14 q!(|| String::new()),
15 q!(|buffer, line| {
16 buffer.push_str(&line);
17 buffer.push_str("\r\n");
18
19 line.trim().is_empty()
21 }),
22 )
23 .map_with_key(q!(|(id, raw_request)| {
24 let lines: Vec<&str> = raw_request.lines().collect();
25
26 let request_line = lines.first().unwrap_or(&"");
28 let parts: Vec<&str> = request_line.split_whitespace().collect();
29 let method = parts.first().unwrap_or(&"GET");
30 let path = parts.get(1).unwrap_or(&"/");
31 let version_str = parts.get(2).unwrap_or(&"HTTP/1.1");
32 let version = if version_str.ends_with("1.0") { 0 } else { 1 };
33
34 let mut user_agent = "Unknown";
36 let mut host = "Unknown";
37
38 for line in &lines[1..] {
39 if line.trim().is_empty() {
40 break;
41 }
42 if let Some(colon_pos) = line.find(':') {
43 let name = line[..colon_pos].trim();
44 let value = line[colon_pos + 1..].trim();
45
46 match name.to_lowercase().as_str() {
47 "user-agent" => user_agent = value,
48 "host" => host = value,
49 _ => {}
50 }
51 }
52 }
53
54 let html_content = format!(
55 "<!DOCTYPE html>\
56 <html><head><title>Hello from Hydro!</title></head>\
57 <body>\
58 <h1>🌊 Hello from Hydro HTTP Server!</h1>\
59 <p><strong>Your browser:</strong> {}</p>\
60 <p><strong>Host:</strong> {}</p>\
61 <p><strong>Method:</strong> {}</p>\
62 <p><strong>Path:</strong> {}</p>\
63 <p><strong>HTTP Version:</strong> 1.{}</p>\
64 <p><em>Connection #{}</em></p>\
65 <hr>\
66 <h3>Raw Request:</h3>\
67 <pre>{}</pre>\
68 </body></html>",
69 user_agent, host, method, path, version, id, raw_request
70 );
71
72 let response = format!(
73 "HTTP/1.1 200 OK\r\n\
74 Content-Type: text/html; charset=utf-8\r\n\
75 Content-Length: {}\r\n\
76 Connection: close\r\n\
77 \r\n\
78 {}",
79 html_content.len(),
80 html_content
81 );
82 response
83 }))
84 .inspect_with_key(q!(|(id, response)| println!(
85 "Sending HTTP response to client #{}: {} bytes",
86 id,
87 response.len()
88 )))
89}