mirror of
https://github.com/frappe/gunicorn.git
synced 2026-07-01 18:21:30 +08:00
- Bump version to 25.0.2 - Update copyright year to 2026 in LICENSE and NOTICE - Add license headers to all Python source files - Add changelog entry for 25.0.2
135 lines
4.1 KiB
Python
135 lines
4.1 KiB
Python
#
|
|
# This file is part of gunicorn released under the MIT license.
|
|
# See the NOTICE for more information.
|
|
|
|
"""
|
|
Example WSGI application demonstrating HTTP/2 with gevent worker.
|
|
|
|
This application showcases various HTTP/2 features including:
|
|
- Basic request/response handling
|
|
- Large file transfers (streaming)
|
|
- Concurrent requests (multiplexing)
|
|
- Server push simulation
|
|
"""
|
|
|
|
import json
|
|
import time
|
|
|
|
|
|
def app(environ, start_response):
|
|
"""WSGI application for HTTP/2 demonstration."""
|
|
path = environ.get('PATH_INFO', '/')
|
|
method = environ.get('REQUEST_METHOD', 'GET')
|
|
|
|
# Root endpoint
|
|
if path == '/':
|
|
body = b'Hello from HTTP/2 with Gevent!'
|
|
status = '200 OK'
|
|
content_type = 'text/plain; charset=utf-8'
|
|
|
|
# Health check
|
|
elif path == '/health':
|
|
body = b'OK'
|
|
status = '200 OK'
|
|
content_type = 'text/plain'
|
|
|
|
# Echo endpoint - returns the request body
|
|
elif path == '/echo':
|
|
content_length = int(environ.get('CONTENT_LENGTH', 0) or 0)
|
|
body = environ['wsgi.input'].read(content_length)
|
|
status = '200 OK'
|
|
content_type = 'application/octet-stream'
|
|
|
|
# JSON endpoint - returns request info as JSON
|
|
elif path == '/info':
|
|
info = {
|
|
'method': method,
|
|
'path': path,
|
|
'protocol': environ.get('SERVER_PROTOCOL', 'unknown'),
|
|
'http_version': environ.get('HTTP_VERSION', '1.1'),
|
|
'server': 'gunicorn with gevent + HTTP/2',
|
|
'headers': {
|
|
k: v for k, v in environ.items()
|
|
if k.startswith('HTTP_')
|
|
}
|
|
}
|
|
body = json.dumps(info, indent=2).encode('utf-8')
|
|
status = '200 OK'
|
|
content_type = 'application/json'
|
|
|
|
# Large response for testing streaming/flow control
|
|
elif path == '/large':
|
|
# Return 1MB of data
|
|
size = 1024 * 1024
|
|
body = b'X' * size
|
|
status = '200 OK'
|
|
content_type = 'application/octet-stream'
|
|
|
|
# Streaming response using generator
|
|
elif path == '/stream':
|
|
def generate():
|
|
for i in range(10):
|
|
yield f'data: chunk {i}\n\n'.encode('utf-8')
|
|
# Small delay to simulate streaming
|
|
time.sleep(0.1)
|
|
|
|
start_response('200 OK', [
|
|
('Content-Type', 'text/event-stream'),
|
|
('Cache-Control', 'no-cache'),
|
|
])
|
|
return generate()
|
|
|
|
# Concurrent test endpoint with configurable delay
|
|
elif path.startswith('/delay'):
|
|
query = environ.get('QUERY_STRING', '')
|
|
try:
|
|
delay = float(query.split('=')[1]) if '=' in query else 0.5
|
|
delay = min(delay, 5.0) # Cap at 5 seconds
|
|
except (ValueError, IndexError):
|
|
delay = 0.5
|
|
|
|
# Use gevent sleep for cooperative yielding
|
|
try:
|
|
import gevent
|
|
gevent.sleep(delay)
|
|
except ImportError:
|
|
time.sleep(delay)
|
|
|
|
body = f'Delayed response after {delay}s'.encode('utf-8')
|
|
status = '200 OK'
|
|
content_type = 'text/plain'
|
|
|
|
# HTTP/2 priority information (if available)
|
|
elif path == '/priority':
|
|
priority_info = {
|
|
'weight': environ.get('HTTP2_PRIORITY_WEIGHT', 'N/A'),
|
|
'depends_on': environ.get('HTTP2_PRIORITY_DEPENDS_ON', 'N/A'),
|
|
'exclusive': environ.get('HTTP2_PRIORITY_EXCLUSIVE', 'N/A'),
|
|
}
|
|
body = json.dumps(priority_info, indent=2).encode('utf-8')
|
|
status = '200 OK'
|
|
content_type = 'application/json'
|
|
|
|
# 404 for unknown paths
|
|
else:
|
|
body = b'Not Found'
|
|
status = '404 Not Found'
|
|
content_type = 'text/plain'
|
|
|
|
response_headers = [
|
|
('Content-Type', content_type),
|
|
('Content-Length', str(len(body))),
|
|
('X-Worker-Type', 'gevent'),
|
|
]
|
|
|
|
start_response(status, response_headers)
|
|
return [body]
|
|
|
|
|
|
# Allow running directly for testing
|
|
if __name__ == '__main__':
|
|
from wsgiref.simple_server import make_server
|
|
server = make_server('localhost', 8000, app)
|
|
print('Test server running on http://localhost:8000')
|
|
server.serve_forever()
|