diff --git a/src/Handler.cpp b/src/Handler.cpp index b45127b..e6e234c 100644 --- a/src/Handler.cpp +++ b/src/Handler.cpp @@ -772,6 +772,11 @@ void Handler::directResponse(Request* req, Response::GenericCode code, ConnectCo } void Handler::handleResponse(ConnectConnection* s, Request* req, Response* res) + ResponsePtr fallback; + if (!res) { + fallback = ResponseAlloc::create(Response::DeliverRequestFail); + res = fallback; + } { FuncCallTimer(); SegmentStr key(req->key()); diff --git a/test/null_response_handling.py b/test/null_response_handling.py new file mode 100644 index 0000000..d2d99e4 --- /dev/null +++ b/test/null_response_handling.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# +# Exercise server write mismatch handling to ensure proxy stays alive +# + +import argparse +import socket +import sys +import time +import redis + + +def run_test(host, port): + # Send a malformed pipelined request and close quickly. + try: + sock = socket.create_connection((host, port), timeout=1.0) + sock.sendall(b"*2\r\n$4\r\nping\r\n$4\r\nping\r\n") + sock.close() + except Exception as exc: + print("WARN: socket setup failed:", exc) + + # Ensure the proxy still accepts connections. + try: + c = redis.StrictRedis(host=host, port=port) + if c.ping() is not True: + print("FAIL: ping did not return True") + return False + except Exception as exc: + print("FAIL: ping after malformed request:", exc) + return False + + return True + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(conflict_handler='resolve', description="Null response handling test") + parser.add_argument("-h", "--host", default="127.0.0.1") + parser.add_argument("-p", "--port", type=int, default=7617) + args = parser.parse_args() + + if run_test(args.host, args.port): + print("PASS: null response handling") + sys.exit(0) + print("FAIL: null response handling") + sys.exit(1) diff --git a/test/run.sh b/test/run.sh index f2586df..82306d8 100755 --- a/test/run.sh +++ b/test/run.sh @@ -62,6 +62,7 @@ PUBSUB_EXIT=0 PUBSUB_MESSAGE_EXIT=0 PUBSUB_ORDER_EXIT=0 PUBSUB_RESET_EXIT=0 +NULL_RESPONSE_EXIT=0 uv run python3 test/basic.py || BASIC_EXIT=$? uv run python3 test/pubsub_minimal.py -p 7617 || PUBSUB_REDIS_EXIT=$? @@ -69,7 +70,8 @@ uv run python3 test/pubsub_minimal.py -p 6379 || PUBSUB_MINIMAL_EXIT=$? uv run python3 test/pubsub.py || PUBSUB_EXIT=$? uv run python3 test/pubsub_subscription_order.py -p 7617 || PUBSUB_ORDER_EXIT=$? uv run python3 test/pubsub_parser_reset.py -p 7617 || PUBSUB_RESET_EXIT=$? +uv run python3 test/null_response_handling.py -p 7617 || NULL_RESPONSE_EXIT=$? uv run python3 test/pubsub_message_response.py -p 7617 || PUBSUB_MESSAGE_EXIT=$? -TEST_EXIT=$((BASIC_EXIT + PUBSUB_REDIS_EXIT + PUBSUB_MINIMAL_EXIT + PUBSUB_EXIT + PUBSUB_MESSAGE_EXIT + PUBSUB_ORDER_EXIT + PUBSUB_RESET_EXIT)) +TEST_EXIT=$((BASIC_EXIT + PUBSUB_REDIS_EXIT + PUBSUB_MINIMAL_EXIT + PUBSUB_EXIT + PUBSUB_MESSAGE_EXIT + PUBSUB_ORDER_EXIT + PUBSUB_RESET_EXIT + NULL_RESPONSE_EXIT)) exit $TEST_EXIT