itsi-scheduler 0.2.13 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54e1eb45891e6c80746fd6792f4e0aebce2ac00f10fc59f3f2f0f11cc2361eea
4
- data.tar.gz: 663b7f505b1edf896f4bb3f73ad89407fe486dea0679181277bd242c55d0340d
3
+ metadata.gz: 8805c01ab4ea4fd6224589792a871b59a3c71495ee4763d8b326d071e0c5d054
4
+ data.tar.gz: ce752eefa1e8df13c891dcad689af2ee82d683373643f18af2c2daa9031dd7cb
5
5
  SHA512:
6
- metadata.gz: bd15583060cfa4989fd876f8db9156230beabedfce76dad1ab333b4dd9657594fd341375ac0307df80653e7f05f52c204e793a2abea6091a2f763cc314c390a2
7
- data.tar.gz: 403ec39e2b91fc79da2bee12ef6cb8a86007299447ad752374adaad1243663bbc796ea0fe9150ff6efb878275277dded8aead5b15ff15df1ca787fe11977502f
6
+ metadata.gz: ce0bac7a7ea61036b0b58befccad25c1722521a92ddcfb8b6a538c6cac01f0928feb0d8b0a4b0fd089cae0dd95ab14f22137f96aa289450dd6fe958afc6745b7
7
+ data.tar.gz: 465b97224aa75c8e7ae1085adab18231fa6b852f431fe5562ae56dc6fd30e2024b04db48323d609cb5d4b9ba589c6bc336cd1ddd1da7f3aa8a50c00381dba918
data/Cargo.lock CHANGED
@@ -213,7 +213,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
213
213
 
214
214
  [[package]]
215
215
  name = "itsi-scheduler"
216
- version = "0.2.13"
216
+ version = "0.2.14"
217
217
  dependencies = [
218
218
  "bytes",
219
219
  "derive_more",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-scheduler"
3
- version = "0.2.13"
3
+ version = "0.2.14"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-server"
3
- version = "0.2.13"
3
+ version = "0.2.14"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -88,3 +88,4 @@ percent-encoding = "2.3.1"
88
88
  sha-crypt = "0.5.0"
89
89
  argon2 = "0.5.3"
90
90
  core_affinity = "0.8.3"
91
+ memchr = "2.7.4"
@@ -1,4 +1,4 @@
1
- use bytes::{Bytes, BytesMut};
1
+ use bytes::{Buf, Bytes, BytesMut};
2
2
  use derive_more::Debug;
3
3
  use futures::stream::{unfold, StreamExt};
4
4
  use http::{
@@ -12,6 +12,7 @@ use hyper_util::rt::TokioIo;
12
12
  use itsi_error::Result;
13
13
  use itsi_tracing::error;
14
14
  use magnus::error::Result as MagnusResult;
15
+ use memchr::{memchr, memchr_iter};
15
16
  use parking_lot::RwLock;
16
17
  use std::{
17
18
  collections::HashMap,
@@ -345,13 +346,54 @@ impl ItsiHttpResponse {
345
346
  let header_name: HeaderName = HeaderName::from_bytes(&name).map_err(|e| {
346
347
  itsi_error::ItsiError::InvalidInput(format!("Invalid header name {:?}: {:?}", name, e))
347
348
  })?;
348
- let header_value = unsafe { HeaderValue::from_maybe_shared_unchecked(value) };
349
349
  if let Some(ref mut resp) = *self.data.response.write() {
350
- resp.headers_mut().append(header_name, header_value);
350
+ let headers_mut = resp.headers_mut();
351
+ self.insert_header(headers_mut, &header_name, value);
351
352
  }
352
353
  Ok(())
353
354
  }
354
355
 
356
+ pub fn insert_header(
357
+ &self,
358
+ headers_mut: &mut HeaderMap,
359
+ header_name: &HeaderName,
360
+ value: Bytes,
361
+ ) {
362
+ static MAX_SPLIT_HEADERS: usize = 100;
363
+
364
+ let mut start = 0usize;
365
+ let mut emitted = 0usize;
366
+
367
+ for idx in memchr_iter(b'\n', &value).chain(std::iter::once(value.len())) {
368
+ if idx == start {
369
+ start += 1;
370
+ continue;
371
+ }
372
+
373
+ let mut part = value.slice(start..idx);
374
+ if part.ends_with(b"\r") {
375
+ part.truncate(part.len() - 1);
376
+ }
377
+ if let Some(&(b' ' | b'\t')) = part.first() {
378
+ part.advance(1);
379
+ }
380
+ if memchr(0, &part).is_some() || part.iter().any(|&b| b < 0x20) {
381
+ warn!("stripped control char from header {:?}", header_name);
382
+ start = idx + 1;
383
+ continue;
384
+ }
385
+
386
+ emitted += 1;
387
+ if emitted > MAX_SPLIT_HEADERS {
388
+ break;
389
+ }
390
+
391
+ let hv = unsafe { HeaderValue::from_maybe_shared_unchecked(part) };
392
+ headers_mut.append(header_name, hv);
393
+ start = idx + 1;
394
+ }
395
+ }
396
+
355
397
  pub fn add_headers(&self, headers: HashMap<Bytes, Vec<Bytes>>) -> MagnusResult<()> {
356
398
  if let Some(ref mut resp) = *self.data.response.write() {
357
399
  let headers_mut = resp.headers_mut();
@@ -363,8 +405,7 @@ impl ItsiHttpResponse {
363
405
  ))
364
406
  })?;
365
407
  for value in values {
366
- let header_value = unsafe { HeaderValue::from_maybe_shared_unchecked(value) };
367
- headers_mut.append(&header_name, header_value);
408
+ self.insert_header(headers_mut, &header_name, value);
368
409
  }
369
410
  }
370
411
  }
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Itsi
4
4
  class Scheduler
5
- VERSION = "0.2.13"
5
+ VERSION = "0.2.14"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itsi-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.13
4
+ version: 0.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wouter Coppieters