http compressions stage 3

This commit is contained in:
YK 2024-05-11 09:01:57 +03:00
parent 16b90fe61c
commit be3740f6ed
3 changed files with 45 additions and 13 deletions

20
Cargo.lock generated
View File

@ -68,6 +68,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crc32fast"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if",
]
[[package]]
name = "diff"
version = "0.1.13"
@ -80,6 +89,16 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "flate2"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "gimli"
version = "0.27.3"
@ -98,6 +117,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bytes",
"flate2",
"itertools",
"nom",
"pretty_assertions",

View File

@ -25,7 +25,7 @@ thiserror = "1.0.38" # error handling
tokio = { version = "1.23.0", features = ["full"] } # async networking
nom = "7.1.3" # parser combinators
itertools = "0.11.0" # General iterator helpers
flate2 = "1.0.30"
[dev-dependencies]
pretty_assertions = "1.3.0" # nicer looking assertions

View File

@ -1,6 +1,6 @@
// #![feature(if_let_guard)]
use std::{ collections::HashMap, path::PathBuf, sync::Arc };
use std::{ collections::HashMap, io::Write, path::PathBuf, sync::Arc };
use anyhow::{bail, Result};
use itertools::Itertools;
@ -10,6 +10,8 @@ use tokio::{
net::{ TcpListener, TcpStream },
};
use flate2::{ write::GzEncoder, Compression };
mod utils;
use utils::*;
@ -72,9 +74,6 @@ async fn process (mut stream: TcpStream, args: A) -> Result<()> {
let headers = Headers::parse(&mut data).await;
let encoding = Encoding::parse(headers.get("Accept-Encoding"));
println!("{:?}", headers);
println!("{:?}", encoding);
use Method as M;
let response = match (method, target.as_str()) {
(M::GET, "/") => Response::Empty,
@ -104,8 +103,6 @@ async fn process (mut stream: TcpStream, args: A) -> Result<()> {
_ => Response::_404,
};
println!("{:?}", String::from_utf8_lossy(&response.clone().build()));
let _ = stream.write_all(&response.build()).await;
let _ = stream.flush().await;
@ -143,7 +140,7 @@ impl Headers {
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
enum Encoding {
Gzip,
Invalid,
@ -215,17 +212,31 @@ enum Response {
impl Response {
fn build (self) -> Vec<u8> {
let headers = self.headers().join("\r\n");
let mut headers = self.headers();
let code = self.code();
let mut v: Vec<u8> = f!("HTTP/1.1 {code}\r\n{headers}\r\n\r\n").into();
let mut v: Vec<u8> = vec![];
let mut write_response_header = |headers: Vec<String>| v.extend_from_slice(format!("HTTP/1.1 {code}\r\n{}\r\n\r\n", headers.join("\r\n")).as_bytes());
match self {
Self::OctetStream(bytes) => {
write_response_header(headers);
v.extend_from_slice(&bytes);
},
Self::TextPlain(text, _) => {
v.extend_from_slice(text.as_bytes());
Self::TextPlain(text, encodings) => {
if encodings.contains(&Encoding::Gzip) {
let mut enc = GzEncoder::new(vec![], Compression::default());
enc.write_all(text.as_bytes()).unwrap();
let b = enc.finish().unwrap();
headers.push(format!("Content-Length: {}", b.len()));
write_response_header(headers);
v.extend_from_slice(&b);
} else {
write_response_header(headers);
v.extend_from_slice(text.as_bytes());
}
},
_ => ()
}
@ -248,10 +259,11 @@ impl Response {
Self::TextPlain(text, enc) => {
let mut v = vec![
f!("Content-Type: text/plain"),
format!("Content-Length: {}", text.len()),
];
if !enc.contains(&Encoding::Gzip) { v.push(format!("Content-Length: {}", text.len())) }
let enc = enc.into_iter().map(Encoding::header).filter(|e| !e.is_empty()).join(", ");
if !enc.is_empty() { v.push(f!("Content-Encoding: {enc}")) }
v
},
Self::OctetStream(bytes) => vec![