use global Header trait

This commit is contained in:
yggverse 2025-02-22 21:56:43 +02:00
parent 91077d3420
commit 44419afc16
18 changed files with 163 additions and 362 deletions

View file

@ -13,26 +13,11 @@ pub struct Titan<'a> {
impl<'a> Titan<'a> {
pub fn from_bytes(buffer: &'a [u8]) -> Result<Self> {
use crate::Header;
use regex::Regex;
let mut l: usize = 0;
for b in buffer {
l += 1;
if l > 1024 {
bail!("Max header length reached!")
}
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
}
let header = from_utf8(&buffer[..l])?;
let header = from_utf8(buffer.header_bytes()?)?;
Ok(Self {
data: &buffer[l..],
data: &buffer[header.len() + 2..],
size: match Regex::new(r"size=(\d+)")?.captures(header) {
Some(c) => match c.get(1) {
Some(v) => match v.as_str().parse::<usize>() {

View file

@ -11,31 +11,21 @@ impl Expected {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl NotAuthorized {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl NotValid {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl BadRequest {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl General {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl Gone {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl NotFound {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl ProxyRequestRefused {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl CgiError {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl General {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl ProxyError {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl ServerUnavailable {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl SlowDown {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl Default {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,31 +11,21 @@ impl Sensitive {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut m = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
m.push(*b)
}
Ok(Self {
message: String::from_utf8(m).map(|m| if m.is_empty() { None } else { Some(m) })?,
message: String::from_utf8((&h[3..]).to_vec()).map(|m| {
if m.is_empty() {
None
} else {
Some(m)
}
})?,
})
}

View file

@ -11,35 +11,18 @@ impl Permanent {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut t = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
t.push(*b)
}
Ok(Self {
target: if t.is_empty() {
target: if h.is_empty() {
bail!("Target required")
} else {
String::from_utf8(t)?
String::from_utf8((&h[3..]).to_vec())?
},
})
}

View file

@ -11,35 +11,18 @@ impl Temporary {
/// Build `Self` from UTF-8 header bytes
/// * expected buffer includes leading status code, message, CRLF
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
// calculate length once
let len = buffer.len();
// validate headers for this response type
if !(3..=1024).contains(&len) {
bail!("Unexpected header length")
}
if buffer
.get(..2)
use crate::Header;
let h = buffer.header_bytes()?;
if h.get(..2)
.is_none_or(|c| c[0] != CODE[0] || c[1] != CODE[1])
{
bail!("Invalid status code")
}
// collect data bytes
let mut t = Vec::with_capacity(len);
for b in buffer[3..].iter() {
if *b == b'\r' {
continue;
}
if *b == b'\n' {
break;
}
t.push(*b)
}
Ok(Self {
target: if t.is_empty() {
target: if h.is_empty() {
bail!("Target required")
} else {
String::from_utf8(t)?
String::from_utf8((&h[3..]).to_vec())?
},
})
}