Skip to content

Commit dbe5fd3

Browse files
kimonusedsiper
authored andcommitted
tests: integration: cover empty HTTP header values
Add real-server POST coverage matching #12174 for empty and whitespace-only generic fields, and verify that the request body is forwarded successfully. Cover empty Connection and Transfer-Encoding values plus empty and whitespace-only Content-Length fields followed immediately by numeric header or body data. Rejected requests must close or return 400, never hang or forward a payload. These tests exercise Monkey 1.8.9 now bundled in Fluent Bit by #12212. Signed-off-by: kimonus <kimonus@users.noreply.github.com>
1 parent 6df3532 commit dbe5fd3

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

tests/integration/scenarios/in_http/tests/test_in_http_001.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33
import os
44
import logging
5+
import socket
56
import time
67

78
import pytest
@@ -66,6 +67,28 @@ def send_requests(conn, num_requests, headers, json_payload):
6667
return responses
6768

6869

70+
def send_raw_http1_request(port, request):
71+
response = bytearray()
72+
73+
with socket.create_connection(("127.0.0.1", port), timeout=2) as connection:
74+
connection.settimeout(2)
75+
connection.sendall(request)
76+
77+
while len(response) < 4096 and b"\r\n" not in response:
78+
try:
79+
data = connection.recv(4096 - len(response))
80+
except ConnectionResetError:
81+
break
82+
except socket.timeout:
83+
pytest.fail("HTTP/1 server did not respond or close the connection")
84+
85+
if not data:
86+
break
87+
response.extend(data)
88+
89+
return bytes(response)
90+
91+
6992
def test_send_data():
7093
try:
7194
service = Service("in_http_config")
@@ -150,6 +173,88 @@ def test_in_http_rejects_get_requests():
150173
assert result["status_code"] >= 400
151174

152175

176+
def test_in_http_accepts_post_with_empty_generic_headers():
177+
service = Service("in_http_config")
178+
body = b'{"message":"empty-header"}'
179+
request = (
180+
b"POST / HTTP/1.1\r\n"
181+
b"Host: localhost\r\n"
182+
b"Content-Type: application/json\r\n"
183+
+ f"Content-Length: {len(body)}\r\n".encode()
184+
+ b"X-Empty:\r\n"
185+
b"X-Empty-Whitespace: \t\r\n"
186+
b"Connection: close\r\n"
187+
b"\r\n"
188+
+ body
189+
)
190+
191+
try:
192+
service.start()
193+
response = send_raw_http1_request(service.flb_listener_port, request)
194+
forwarded_payloads = service.read_forwarded_payloads()
195+
finally:
196+
service.stop()
197+
198+
assert b"HTTP/1.1 201" in response
199+
assert len(forwarded_payloads) == 1
200+
assert forwarded_payloads[0][0]["message"] == "empty-header"
201+
202+
203+
def test_in_http_accepts_empty_connection_and_transfer_encoding():
204+
service = Service("in_http_config")
205+
body = b'{"message":"empty-semantic-headers"}'
206+
request = (
207+
b"POST / HTTP/1.1\r\n"
208+
b"Host: localhost\r\n"
209+
b"Content-Type: application/json\r\n"
210+
+ f"Content-Length: {len(body)}\r\n".encode()
211+
+ b"Connection:\r\n"
212+
b"Transfer-Encoding: \t\r\n"
213+
b"Connection: close\r\n"
214+
b"\r\n"
215+
+ body
216+
)
217+
218+
try:
219+
service.start()
220+
response = send_raw_http1_request(service.flb_listener_port, request)
221+
forwarded_payloads = service.read_forwarded_payloads()
222+
finally:
223+
service.stop()
224+
225+
assert b"HTTP/1.1 201" in response
226+
assert len(forwarded_payloads) == 1
227+
assert forwarded_payloads[0][0]["message"] == "empty-semantic-headers"
228+
229+
230+
@pytest.mark.parametrize("header_value", [b"", b" \t"], ids=["empty", "whitespace"])
231+
@pytest.mark.parametrize(
232+
"following_data",
233+
[b"1-X: value\r\nConnection: close\r\n\r\n1", b"\r\n1"],
234+
ids=["numeric-header", "numeric-body"],
235+
)
236+
def test_in_http_rejects_empty_content_length(header_value, following_data):
237+
service = Service("in_http_config")
238+
request = (
239+
b"POST / HTTP/1.1\r\n"
240+
b"Host: localhost\r\n"
241+
b"Content-Type: application/json\r\n"
242+
b"Content-Length:" + header_value + b"\r\n"
243+
+ following_data
244+
)
245+
246+
try:
247+
service.start()
248+
response = send_raw_http1_request(service.flb_listener_port, request)
249+
time.sleep(0.5)
250+
forwarded_payloads = list(data_storage["payloads"])
251+
finally:
252+
service.stop()
253+
254+
assert response == b"" or b"HTTP/1.1 400" in response
255+
assert forwarded_payloads == []
256+
257+
153258
@pytest.mark.parametrize(
154259
"case",
155260
[

0 commit comments

Comments
 (0)