mirror of
https://github.com/frappe/gunicorn.git
synced 2026-07-01 18:21:30 +08:00
Add docker integration tests for simple ASGI (HTTP protocol)
Tests the ASGI worker with direct HTTP requests without uWSGI protocol. Includes tests for GET, POST, query strings, path handling, keepalive, large bodies, and custom headers.
This commit is contained in:
parent
47b1cb82b8
commit
6575d86251
18
tests/docker/asgi/Dockerfile
Normal file
18
tests/docker/asgi/Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Copy gunicorn source
|
||||
COPY . /build/
|
||||
|
||||
# Install gunicorn from source
|
||||
RUN pip install --no-cache-dir -e .
|
||||
|
||||
# Copy test app
|
||||
WORKDIR /app
|
||||
COPY tests/docker/asgi/app.py /app/
|
||||
|
||||
# Expose HTTP port
|
||||
EXPOSE 8000
|
||||
|
||||
CMD ["gunicorn", "--worker-class", "asgi", "--bind", "0.0.0.0:8000", "app:app"]
|
||||
45
tests/docker/asgi/app.py
Normal file
45
tests/docker/asgi/app.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""Simple ASGI test application for HTTP protocol testing."""
|
||||
|
||||
|
||||
async def app(scope, receive, send):
|
||||
"""Simple ASGI application that echoes request info."""
|
||||
if scope["type"] == "lifespan":
|
||||
while True:
|
||||
message = await receive()
|
||||
if message["type"] == "lifespan.startup":
|
||||
await send({"type": "lifespan.startup.complete"})
|
||||
elif message["type"] == "lifespan.shutdown":
|
||||
await send({"type": "lifespan.shutdown.complete"})
|
||||
return
|
||||
|
||||
if scope["type"] != "http":
|
||||
return
|
||||
|
||||
# Read body
|
||||
body = b""
|
||||
while True:
|
||||
message = await receive()
|
||||
body += message.get("body", b"")
|
||||
if not message.get("more_body", False):
|
||||
break
|
||||
|
||||
# Build response
|
||||
method = scope["method"]
|
||||
path = scope["path"]
|
||||
query = scope.get("query_string", b"").decode("utf-8")
|
||||
|
||||
response_body = f"Method: {method}\nPath: {path}\nQuery: {query}\nBody: {body.decode('utf-8')}\n"
|
||||
response_bytes = response_body.encode("utf-8")
|
||||
|
||||
await send({
|
||||
"type": "http.response.start",
|
||||
"status": 200,
|
||||
"headers": [
|
||||
[b"content-type", b"text/plain"],
|
||||
[b"content-length", str(len(response_bytes)).encode()],
|
||||
],
|
||||
})
|
||||
await send({
|
||||
"type": "http.response.body",
|
||||
"body": response_bytes,
|
||||
})
|
||||
14
tests/docker/asgi/docker-compose.yml
Normal file
14
tests/docker/asgi/docker-compose.yml
Normal file
@ -0,0 +1,14 @@
|
||||
services:
|
||||
gunicorn:
|
||||
build:
|
||||
context: ../../..
|
||||
dockerfile: tests/docker/asgi/Dockerfile
|
||||
command: >
|
||||
gunicorn
|
||||
--worker-class asgi
|
||||
--bind 0.0.0.0:8000
|
||||
--workers 1
|
||||
--log-level debug
|
||||
app:app
|
||||
ports:
|
||||
- "8080:8000"
|
||||
116
tests/docker/asgi/test_asgi.sh
Executable file
116
tests/docker/asgi/test_asgi.sh
Executable file
@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
# Integration test for ASGI HTTP protocol support
|
||||
#
|
||||
# This script tests that gunicorn's ASGI worker correctly handles
|
||||
# HTTP requests directly (without uWSGI protocol).
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Use IPv4 explicitly to avoid Docker IPv6 issues
|
||||
BASE_URL="http://127.0.0.1:8080"
|
||||
|
||||
cleanup() {
|
||||
echo "Cleaning up..."
|
||||
docker compose down -v 2>/dev/null || true
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "=== Building and starting containers ==="
|
||||
docker compose up -d --build
|
||||
|
||||
echo "=== Waiting for services to be ready ==="
|
||||
sleep 5
|
||||
|
||||
echo "=== Running tests ==="
|
||||
|
||||
# Test 1: Simple GET request
|
||||
echo "Test 1: Simple GET request"
|
||||
RESPONSE=$(curl -s "$BASE_URL/")
|
||||
if echo "$RESPONSE" | grep -q "Method: GET"; then
|
||||
echo " PASS: GET request works"
|
||||
else
|
||||
echo " FAIL: GET request failed"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 2: GET with query string
|
||||
echo "Test 2: GET with query string"
|
||||
RESPONSE=$(curl -s "$BASE_URL/search?q=test&page=1")
|
||||
if echo "$RESPONSE" | grep -q "Query: q=test&page=1"; then
|
||||
echo " PASS: Query string works"
|
||||
else
|
||||
echo " FAIL: Query string failed"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: POST with body
|
||||
echo "Test 3: POST with body"
|
||||
RESPONSE=$(curl -s -X POST -d "hello=world" "$BASE_URL/submit")
|
||||
if echo "$RESPONSE" | grep -q "Method: POST" && echo "$RESPONSE" | grep -q "Body: hello=world"; then
|
||||
echo " PASS: POST with body works"
|
||||
else
|
||||
echo " FAIL: POST with body failed"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: Path handling
|
||||
echo "Test 4: Path handling"
|
||||
RESPONSE=$(curl -s "$BASE_URL/api/v1/users")
|
||||
if echo "$RESPONSE" | grep -q "Path: /api/v1/users"; then
|
||||
echo " PASS: Path handling works"
|
||||
else
|
||||
echo " FAIL: Path handling failed"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 5: Multiple requests (keepalive)
|
||||
echo "Test 5: Multiple requests (keepalive)"
|
||||
for i in 1 2 3; do
|
||||
RESPONSE=$(curl -s "$BASE_URL/request/$i")
|
||||
if ! echo "$RESPONSE" | grep -q "Path: /request/$i"; then
|
||||
echo " FAIL: Request $i failed"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo " PASS: Multiple requests work"
|
||||
|
||||
# Test 6: Large POST body
|
||||
echo "Test 6: Large POST body"
|
||||
LARGE_BODY=$(python3 -c "print('x' * 10000)")
|
||||
RESPONSE=$(curl -s -X POST -d "$LARGE_BODY" "$BASE_URL/large")
|
||||
if echo "$RESPONSE" | grep -q "Method: POST" && echo "$RESPONSE" | grep -c "x" | grep -q "10000"; then
|
||||
echo " PASS: Large POST body works"
|
||||
else
|
||||
# Verify body length in response
|
||||
BODY_LINE=$(echo "$RESPONSE" | grep "Body:")
|
||||
BODY_LEN=${#BODY_LINE}
|
||||
if [ "$BODY_LEN" -gt 10000 ]; then
|
||||
echo " PASS: Large POST body works"
|
||||
else
|
||||
echo " FAIL: Large POST body failed"
|
||||
echo " Response length: $BODY_LEN"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Test 7: HTTP headers
|
||||
echo "Test 7: Custom headers"
|
||||
RESPONSE=$(curl -s -H "X-Custom-Header: test-value" "$BASE_URL/headers")
|
||||
if echo "$RESPONSE" | grep -q "Method: GET"; then
|
||||
echo " PASS: Custom headers work"
|
||||
else
|
||||
echo " FAIL: Custom headers failed"
|
||||
echo " Response: $RESPONSE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== All tests passed! ==="
|
||||
Loading…
x
Reference in New Issue
Block a user