Serve the `/code` sync protocol: any GET whose path ends in `/code` gets the canned `SyncPack`; everything else is a 404. One request per connection (`Connection: close`), which is all reqwest needs.
(pack: SyncPack)
| 123 | /// the canned `SyncPack`; everything else is a 404. One request per |
| 124 | /// connection (`Connection: close`), which is all reqwest needs. |
| 125 | fn spawn_sync_server(pack: SyncPack) -> String { |
| 126 | let listener = TcpListener::bind("127.0.0.1:0").expect("bind test server"); |
| 127 | let addr = listener.local_addr().expect("local addr"); |
| 128 | let pack_bytes = pack.encode().expect("encode sync pack"); |
| 129 | |
| 130 | std::thread::spawn(move || { |
| 131 | for stream in listener.incoming().flatten() { |
| 132 | let mut stream = stream; |
| 133 | let mut buf = Vec::new(); |
| 134 | let mut tmp = [0u8; 4096]; |
| 135 | // Read the request head + body (Content-Length bounded). |
| 136 | loop { |
| 137 | let n = match stream.read(&mut tmp) { |
| 138 | Ok(0) | Err(_) => break, |
| 139 | Ok(n) => n, |
| 140 | }; |
| 141 | buf.extend_from_slice(&tmp[..n]); |
| 142 | if let Some(head_end) = find_head_end(&buf) { |
| 143 | let head = String::from_utf8_lossy(&buf[..head_end]).to_string(); |
| 144 | if let Some(len) = content_length(&head) { |
| 145 | if buf.len() >= head_end + 4 + len { |
| 146 | break; |
| 147 | } |
| 148 | } else { |
| 149 | break; |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | let head = String::from_utf8_lossy(&buf).to_string(); |
| 154 | let path = head.split_whitespace().nth(1).unwrap_or(""); |
| 155 | |
| 156 | let (status, body) = if path.ends_with("/code") { |
| 157 | ("200 OK", pack_bytes.clone()) |
| 158 | } else { |
| 159 | ("404 Not Found", b"not found".to_vec()) |
| 160 | }; |
| 161 | let response = format!( |
| 162 | "HTTP/1.1 {status}\r\nContent-Type: application/octet-stream\r\n\ |
| 163 | X-Atomic-Min-Version: 0.16.2\r\nContent-Length: {}\r\nConnection: close\r\n\r\n", |
| 164 | body.len() |
| 165 | ); |
| 166 | let _ = stream.write_all(response.as_bytes()); |
| 167 | let _ = stream.write_all(&body); |
| 168 | let _ = stream.flush(); |
| 169 | } |
| 170 | }); |
| 171 | |
| 172 | format!("http://{}", addr) |
| 173 | } |
| 174 | |
| 175 | fn find_head_end(buf: &[u8]) -> Option<usize> { |
| 176 | buf.windows(4).position(|w| w == b"\r\n\r\n") |
no test coverage detected