Skip to content

Commit e26c4b7

Browse files
authored
No content length or chunked case can occur with HTTP/1.1 too (#834)
* No content length or chunked case can occur with `HTTP/1.1` too * `WPS331` false-positive
1 parent 90820b0 commit e26c4b7

File tree

5 files changed

+21
-9
lines changed

5 files changed

+21
-9
lines changed

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ lib-profile:
141141
--hostname 127.0.0.1 \
142142
--num-acceptors 1 \
143143
--num-workers 1 \
144-
--disable-http-proxy \
145144
--enable-web-server \
146145
--plugin proxy.plugin.WebServerPlugin \
147146
--local-executor \

proxy/core/acceptor/threadless.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,16 +224,13 @@ async def _selected_events(self) -> Tuple[
224224
work_by_ids[key.data][1].append(key.fileobj)
225225
return (work_by_ids, new_work_available)
226226

227-
async def _wait_for_tasks(self) -> None:
227+
async def _wait_for_tasks(self) -> Set['asyncio.Task[bool]']:
228228
finished, self.unfinished = await asyncio.wait(
229229
self.unfinished,
230230
timeout=self.wait_timeout,
231231
return_when=asyncio.FIRST_COMPLETED,
232232
)
233-
for task in finished:
234-
if task.result():
235-
self._cleanup(task._work_id) # type: ignore
236-
# self.cleanup(int(task.get_name()))
233+
return finished # noqa: WPS331
237234

238235
def _fromfd(self, fileno: int) -> socket.socket:
239236
return socket.fromfd(
@@ -299,7 +296,11 @@ async def _run_once(self) -> bool:
299296
# Invoke Threadless.handle_events
300297
self.unfinished.update(self._create_tasks(work_by_ids))
301298
# logger.debug('Executing {0} works'.format(len(self.unfinished)))
302-
await self._wait_for_tasks()
299+
# Cleanup finished tasks
300+
for task in await self._wait_for_tasks():
301+
if task.result():
302+
self._cleanup(task._work_id) # type: ignore
303+
# self.cleanup(int(task.get_name()))
303304
# logger.debug(
304305
# 'Done executing works, {0} pending, {1} registered'.format(
305306
# len(self.unfinished), len(self.registered_events_by_work_ids),

proxy/core/connection/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def close(self) -> bool:
7575
return self.closed
7676

7777
def has_buffer(self) -> bool:
78-
return self._num_buffer > 0
78+
return self._num_buffer != 0
7979

8080
def queue(self, mv: memoryview) -> None:
8181
self.buffer.append(mv)

proxy/http/handler.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ def is_inactive(self) -> bool:
117117
def shutdown(self) -> None:
118118
try:
119119
# Flush pending buffer in threaded mode only.
120+
#
120121
# For threadless mode, BaseTcpServerHandler implements
121122
# the must_flush_before_shutdown logic automagically.
122123
if self.selector and self.work.has_buffer():
@@ -139,6 +140,15 @@ def shutdown(self) -> None:
139140
except OSError:
140141
pass
141142
finally:
143+
# Section 4.2.2.13 of RFC 1122 tells us that a close() with any pending readable data
144+
# could lead to an immediate reset being sent.
145+
#
146+
# "A host MAY implement a 'half-duplex' TCP close sequence, so that an application
147+
# that has called CLOSE cannot continue to read data from the connection.
148+
# If such a host issues a CLOSE call while received data is still pending in TCP,
149+
# or if new data is received after CLOSE is called, its TCP SHOULD send a RST to
150+
# show that data was lost."
151+
#
142152
self.work.connection.close()
143153
logger.debug('Client connection closed')
144154
super().shutdown()

proxy/http/parser/parser.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,9 @@ def _process_line(self, raw: bytes) -> None:
358358
line = raw.split(WHITESPACE, 2)
359359
self.version = line[0]
360360
self.code = line[1]
361-
self.reason = line[2]
361+
# Our own WebServerPlugin example currently doesn't send any reason
362+
if len(line) == 3:
363+
self.reason = line[2]
362364
self.state = httpParserStates.LINE_RCVD
363365

364366
def _process_header(self, raw: bytes) -> None:

0 commit comments

Comments
 (0)