| | 39 | |
|---|
| | 40 | For those of you wanting to understand internals of this module, here's the |
|---|
| | 41 | basic call flow. The server's listening thread runs a very tight loop, |
|---|
| | 42 | sticking incoming connections onto a Queue: |
|---|
| | 43 | |
|---|
| | 44 | server = CherryPyWSGIServer(...) |
|---|
| | 45 | server.start() |
|---|
| | 46 | while True: |
|---|
| | 47 | tick() |
|---|
| | 48 | # This blocks until a request comes in: |
|---|
| | 49 | child = socket.accept() |
|---|
| | 50 | conn = HTTPConnection(child, ...) |
|---|
| | 51 | server.requests.put(conn) |
|---|
| | 52 | |
|---|
| | 53 | Worker threads are kept in a pool and poll the Queue, popping off and then |
|---|
| | 54 | handling each connection in turn. Each connection can consist of an arbitrary |
|---|
| | 55 | number of requests and their responses, so we run a nested loop: |
|---|
| | 56 | |
|---|
| | 57 | while True: |
|---|
| | 58 | conn = server.requests.get() |
|---|
| | 59 | conn.communicate() |
|---|
| | 60 | -> while True: |
|---|
| | 61 | req = HTTPRequest(...) |
|---|
| | 62 | req.parse_request() |
|---|
| | 63 | -> # Read the Request-Line, e.g. "GET /page HTTP/1.1" |
|---|
| | 64 | req.rfile.readline() |
|---|
| | 65 | req.read_headers() |
|---|
| | 66 | req.respond() |
|---|
| | 67 | -> response = wsgi_app(...) |
|---|
| | 68 | try: |
|---|
| | 69 | for chunk in response: |
|---|
| | 70 | if chunk: |
|---|
| | 71 | req.write(chunk) |
|---|
| | 72 | finally: |
|---|
| | 73 | if hasattr(response, "close"): |
|---|
| | 74 | response.close() |
|---|
| | 75 | if req.close_connection: |
|---|
| | 76 | return |
|---|