http compressions stage 3
This commit is contained in:
parent
16b90fe61c
commit
be3740f6ed
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
34
src/main.rs
34
src/main.rs
@ -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, _) => {
|
||||
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![
|
||||
|
||||
Loading…
Reference in New Issue
Block a user