Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ version = "0.1.11"
edition = "2021"
authors = ["Xudong Huang <huangxu008@hotmail.com>"]
repository = "https://github.com/Xudong-Huang/may_minihttp.git"
homepage = "https://github.com/Xudong-Huang/may_minihttp.git"
documentation = "https://docs.rs/may_minihttp"
description = "Mini http server that implemented on top of [may](https://github.com/Xudong-Huang/may)"
readme = "README.md"
Expand Down Expand Up @@ -32,7 +31,7 @@ serde_json = { version = "1", optional = true }
tracing = { version = "0.1", default-features = false, features = ["std"], optional = true }

[dev-dependencies]
atoi = "2"
atoi = "3"
num_cpus = "1.0"
smallvec = "1.1"
env_logger = "0.11"
Expand All @@ -43,12 +42,12 @@ yarte = { version = "0.15", features = ["bytes-buf", "json"] }
buf-min = { version = "0.7", features = ["bytes"] }

mimalloc = { version = "0.1", default-features = false }
nanorand = { version = "0.7", default-features = false, features = ["std", "wyrand"] }
nanorand = { version = "0.8", default-features = false, features = ["std", "wyrand"] }

# Load testing and integration testing
goose = "0.18.1"
gumdrop = "0.8"
testcontainers = "0.15"
testcontainers = "0.28"
tokio = { version = "1", features = ["full"] }
rcgen = "0.14"
flate2 = "1.1"
Expand Down
4 changes: 2 additions & 2 deletions examples/techempower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ mod __impl {
id: 0,
message: "Additional fortune added at request time.",
});
fortunes.sort_by(|it, next| it.message.cmp(next.message));
fortunes.sort_unstable_by(|it, next| it.message.cmp(next.message));

let mut body = unsafe { std::ptr::read(buf) };
ywrite_html!(body, "{{> fortune }}");
Expand Down Expand Up @@ -298,7 +298,7 @@ mod __impl {

fn new_service(&self, id: usize) -> Self::Service {
let db = self.db_pool.get_connection(id);
let rng = WyRand::new();
let rng = WyRand::new_seed(0);
Techempower { db, rng }
}
}
Expand Down
19 changes: 9 additions & 10 deletions src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,19 +694,15 @@ pub(crate) fn decode_with_close<'header, 'buf, 'stream, const N: usize>(
// so we can transfer the mutable reference to Request
let buf: &[u8] = unsafe { std::mem::transmute(req_buf.chunk()) };

// Wait for complete headers before parsing to prevent token errors (issue #18: a head split
// across TCP segments). Only the first MAX_REQUEST_HEAD_BYTES are searched: a head that has
// not ended by then is refused rather than buffered without bound.
// No separate `\r\n\r\n` pre-scan: `httparse` returns `Status::Partial` on any truncated
// head (mid-method, mid-path, mid-header, or no terminating `\r\n\r\n` yet), which maps to
// `Ok(None)` below, and malformed bytes are a permanent 400 whatever arrives later. Only the
// first MAX_REQUEST_HEAD_BYTES are parsed: a head that has not ended by then is refused (431)
// rather than buffered or re-parsed without bound.
let window = &buf[..buf.len().min(MAX_REQUEST_HEAD_BYTES)];
if !window.windows(4).any(|w| w == b"\r\n\r\n") {
if buf.len() >= MAX_REQUEST_HEAD_BYTES {
return reject(431, "request head too large");
}
return Ok(None); // Need more data
}

let header_limit = headers.len();
let status = match req.parse_with_uninit_headers(buf, headers) {
let status = match req.parse_with_uninit_headers(window, headers) {
Ok(s) => s,
Err(httparse::Error::TooManyHeaders) => {
warn!(
Expand All @@ -723,6 +719,9 @@ pub(crate) fn decode_with_close<'header, 'buf, 'stream, const N: usize>(

let len = match status {
httparse::Status::Complete(amt) => amt,
httparse::Status::Partial if buf.len() >= MAX_REQUEST_HEAD_BYTES => {
return reject(431, "request head too large");
}
httparse::Status::Partial => return Ok(None),
};
let framing = framing(&req)?;
Expand Down
2 changes: 1 addition & 1 deletion tests/test_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl ConfigurableTestServer {
// For now, start with default - we'll add configuration support next
let server_handle = thread::spawn(move || {
let _server = HttpServer(TestService)
.start(&format!("127.0.0.1:{}", port))
.start(format!("127.0.0.1:{}", port))
.expect("Failed to start test server");

while !shutdown_clone.load(Ordering::Relaxed) {
Expand Down
Loading