ferron/util/
fcgi_record.rs

1/// Constructs a FastCGI record
2pub fn construct_fastcgi_record(record_type: u8, request_id: u16, content: &[u8]) -> Vec<u8> {
3  // Content and padding lengths (for determining the vector allocation size)
4  let content_length = content.len() as u16;
5  let padding_length = match (content_length % 8) as u8 {
6    0 => 0,
7    remainder => 8 - remainder,
8  };
9
10  // Allocate the vector with the preallocated capacity
11  let mut record = Vec::with_capacity(8 + (content_length as usize) + (padding_length as usize));
12
13  // FastCGI version: FCGI_VERSION_1
14  record.push(1);
15
16  // Record type
17  record.extend_from_slice(&(record_type.to_be_bytes()));
18
19  // Request ID
20  record.extend_from_slice(&(request_id.to_be_bytes()));
21
22  // Content length
23  record.extend_from_slice(&(content_length.to_be_bytes()));
24
25  // Padding length
26  record.extend_from_slice(&(padding_length.to_be_bytes()));
27
28  // Reserved
29  record.push(0);
30
31  // Content
32  record.extend_from_slice(content);
33
34  // Padding
35  record.append(&mut vec![0u8; padding_length as usize]);
36
37  record
38}
39
40#[cfg(test)]
41mod tests {
42  use super::*;
43
44  #[test]
45  fn test_construct_fastcgi_record() {
46    // Test case 1: Empty content
47    let record_type = 1;
48    let request_id = 1234;
49    let content: &[u8] = &[];
50    let expected_record = vec![
51      1, // FastCGI version
52      1, // Record type
53      4, 210, // Request ID
54      0, 0, // Content length
55      0, // Padding length
56      0, // Reserved
57    ];
58    assert_eq!(
59      construct_fastcgi_record(record_type, request_id, content),
60      expected_record
61    );
62
63    // Test case 2: Content with length 5
64    let record_type = 2;
65    let request_id = 5678;
66    let content = b"Hello";
67    let expected_record = vec![
68      1, // FastCGI version
69      2, // Record type
70      22, 46, // Request ID
71      0, 5, // Content length
72      3, // Padding length
73      0, // Reserved
74      72, 101, 108, 108, 111, // Content
75      0, 0, 0, // Padding
76    ];
77    assert_eq!(
78      construct_fastcgi_record(record_type, request_id, content),
79      expected_record
80    );
81
82    // Test case 3: Content with length 8 (no padding needed)
83    let record_type = 3;
84    let request_id = 9012;
85    let content = b"12345678";
86    let expected_record = vec![
87      1, // FastCGI version
88      3, // Record type
89      35, 52, // Request ID
90      0, 8, // Content length
91      0, // Padding length
92      0, // Reserved
93      49, 50, 51, 52, 53, 54, 55, 56, // Content
94    ];
95    assert_eq!(
96      construct_fastcgi_record(record_type, request_id, content),
97      expected_record
98    );
99  }
100}