@@ -138,81 +138,76 @@ async def handshake(
138
138
Perform the opening handshake.
139
139
140
140
"""
141
- # May raise CancelledError if open_timeout is exceeded.
142
141
await asyncio .wait (
143
142
[self .request_rcvd , self .connection_lost_waiter ],
144
143
return_when = asyncio .FIRST_COMPLETED ,
145
144
)
146
145
147
- if self .request is None :
148
- raise ConnectionError ("connection closed during handshake" )
149
-
150
- async with self .send_context (expected_state = CONNECTING ):
151
- response = None
152
-
153
- if process_request is not None :
154
- try :
155
- response = process_request (self , self .request )
156
- if isinstance (response , Awaitable ):
157
- response = await response
158
- except Exception as exc :
159
- self .protocol .handshake_exc = exc
160
- self .logger .error ("opening handshake failed" , exc_info = True )
161
- response = self .protocol .reject (
162
- http .HTTPStatus .INTERNAL_SERVER_ERROR ,
163
- (
164
- "Failed to open a WebSocket connection.\n "
165
- "See server log for more information.\n "
166
- ),
167
- )
168
-
169
- if response is None :
170
- if self .server .is_serving ():
171
- self .response = self .protocol .accept (self .request )
146
+ if self .request is not None :
147
+ async with self .send_context (expected_state = CONNECTING ):
148
+ response = None
149
+
150
+ if process_request is not None :
151
+ try :
152
+ response = process_request (self , self .request )
153
+ if isinstance (response , Awaitable ):
154
+ response = await response
155
+ except Exception as exc :
156
+ self .protocol .handshake_exc = exc
157
+ response = self .protocol .reject (
158
+ http .HTTPStatus .INTERNAL_SERVER_ERROR ,
159
+ (
160
+ "Failed to open a WebSocket connection.\n "
161
+ "See server log for more information.\n "
162
+ ),
163
+ )
164
+
165
+ if response is None :
166
+ if self .server .is_serving ():
167
+ self .response = self .protocol .accept (self .request )
168
+ else :
169
+ self .response = self .protocol .reject (
170
+ http .HTTPStatus .SERVICE_UNAVAILABLE ,
171
+ "Server is shutting down.\n " ,
172
+ )
172
173
else :
173
- self .response = self .protocol .reject (
174
- http .HTTPStatus .SERVICE_UNAVAILABLE ,
175
- "Server is shutting down.\n " ,
176
- )
177
- else :
178
- assert isinstance (response , Response ) # help mypy
179
- self .response = response
180
-
181
- if server_header :
182
- self .response .headers ["Server" ] = server_header
183
-
184
- response = None
185
-
186
- if process_response is not None :
187
- try :
188
- response = process_response (self , self .request , self .response )
189
- if isinstance (response , Awaitable ):
190
- response = await response
191
- except Exception as exc :
192
- self .protocol .handshake_exc = exc
193
- self .logger .error ("opening handshake failed" , exc_info = True )
194
- response = self .protocol .reject (
195
- http .HTTPStatus .INTERNAL_SERVER_ERROR ,
196
- (
197
- "Failed to open a WebSocket connection.\n "
198
- "See server log for more information.\n "
199
- ),
200
- )
201
-
202
- if response is not None :
203
- assert isinstance (response , Response ) # help mypy
204
- self .response = response
205
-
206
- self .protocol .send_response (self .response )
174
+ assert isinstance (response , Response ) # help mypy
175
+ self .response = response
176
+
177
+ if server_header :
178
+ self .response .headers ["Server" ] = server_header
179
+
180
+ response = None
181
+
182
+ if process_response is not None :
183
+ try :
184
+ response = process_response (self , self .request , self .response )
185
+ if isinstance (response , Awaitable ):
186
+ response = await response
187
+ except Exception as exc :
188
+ self .protocol .handshake_exc = exc
189
+ response = self .protocol .reject (
190
+ http .HTTPStatus .INTERNAL_SERVER_ERROR ,
191
+ (
192
+ "Failed to open a WebSocket connection.\n "
193
+ "See server log for more information.\n "
194
+ ),
195
+ )
196
+
197
+ if response is not None :
198
+ assert isinstance (response , Response ) # help mypy
199
+ self .response = response
200
+
201
+ self .protocol .send_response (self .response )
202
+
203
+ # self.protocol.handshake_exc is always set when the connection is lost
204
+ # before receiving a request, when the request cannot be parsed, or when
205
+ # the response fails the handshake.
207
206
208
207
if self .protocol .handshake_exc is None :
209
208
self .start_keepalive ()
210
209
else :
211
- try :
212
- async with asyncio_timeout (self .close_timeout ):
213
- await self .connection_lost_waiter
214
- finally :
215
- raise self .protocol .handshake_exc
210
+ raise self .protocol .handshake_exc
216
211
217
212
def process_event (self , event : Event ) -> None :
218
213
"""
@@ -359,25 +354,35 @@ async def conn_handler(self, connection: ServerConnection) -> None:
359
354
360
355
"""
361
356
try :
362
- # On failure, handshake() closes the transport, raises an
363
- # exception, and logs it.
364
357
async with asyncio_timeout (self .open_timeout ):
365
- await connection .handshake (
366
- self .process_request ,
367
- self .process_response ,
368
- self .server_header ,
369
- )
358
+ try :
359
+ await connection .handshake (
360
+ self .process_request ,
361
+ self .process_response ,
362
+ self .server_header ,
363
+ )
364
+ except asyncio .CancelledError :
365
+ connection .close_transport ()
366
+ raise
367
+ except Exception :
368
+ connection .logger .error ("opening handshake failed" , exc_info = True )
369
+ connection .close_transport ()
370
+ return
370
371
371
372
try :
372
373
await self .handler (connection )
373
374
except Exception :
374
- self .logger .error ("connection handler failed" , exc_info = True )
375
+ connection .logger .error ("connection handler failed" , exc_info = True )
375
376
await connection .close (CloseCode .INTERNAL_ERROR )
376
377
else :
377
378
await connection .close ()
378
379
379
- except Exception :
380
- # Don't leak connections on errors.
380
+ except TimeoutError :
381
+ # When the opening handshake times out, there's nothing to log.
382
+ pass
383
+
384
+ except Exception : # pragma: no cover
385
+ # Don't leak connections on unexpected errors.
381
386
connection .transport .abort ()
382
387
383
388
finally :
0 commit comments