Skip to content

Commit 464dbf5

Browse files
committed
overload http1 and update doc
1 parent 2fc3989 commit 464dbf5

1 file changed

Lines changed: 76 additions & 13 deletions

File tree

awscrt/http.py

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -594,12 +594,21 @@ def update_window(self, increment_size: int) -> None:
594594
def write_data(self,
595595
data_stream: Union[InputStream, Any],
596596
end_stream: bool = False) -> "concurrent.futures.Future":
597-
'''Write a chunk of data to the request body stream.
597+
'''Write data to the request body.
598598
599599
Works for both HTTP/1.1 and HTTP/2 streams.
600600
The stream must have been created with ``manual_write=True``.
601601
You must call :meth:`activate()` before using this method.
602602
603+
.. note::
604+
This is the unified API for manual body writes, superseding the
605+
C-level ``aws_http1_stream_write_chunk``. Use ``write_data()``
606+
for all new code — the old chunked-write API is deprecated.
607+
608+
See :meth:`HttpClientStream.write_data` and
609+
:meth:`Http2ClientStream.write_data` for protocol-specific
610+
behaviour and constraints.
611+
603612
Args:
604613
data_stream (InputStream): Data to write. If not an InputStream,
605614
it will be wrapped in one. Can be None to write zero bytes.
@@ -659,6 +668,50 @@ def activate(self) -> None:
659668
"""
660669
_awscrt.http_client_stream_activate(self)
661670

671+
def write_data(self,
672+
data_stream: Union[InputStream, Any],
673+
end_stream: bool = False) -> "concurrent.futures.Future":
674+
'''Write data to the HTTP/1.1 request body.
675+
676+
The stream must have been created with ``manual_write=True`` and
677+
:meth:`activate()` must have been called before using this method.
678+
679+
.. important::
680+
HTTP/1.1 does **not** support combining a body stream with manual
681+
writes. The underlying H1 encoder uses a modal state machine that
682+
commits to a single body-delivery path at initialisation time.
683+
If the :class:`HttpRequest` was created with a ``body_stream``,
684+
calling this method will raise :class:`RuntimeError`.
685+
686+
HTTP/2 does not have this limitation — see
687+
:meth:`Http2ClientStream.write_data`.
688+
689+
.. deprecated:: 0.x
690+
This method supersedes the C-level ``aws_http1_stream_write_chunk``
691+
API. Use ``write_data`` for all manual body writes on both HTTP/1.1
692+
and HTTP/2 streams.
693+
694+
Args:
695+
data_stream: Data to write. Wrapped in :class:`InputStream` if
696+
needed. ``None`` sends zero bytes.
697+
end_stream (bool): ``True`` if this is the last write.
698+
699+
Returns:
700+
concurrent.futures.Future: Completes with ``None`` on success.
701+
702+
Raises:
703+
RuntimeError: If the request has a ``body_stream`` set.
704+
'''
705+
if self._request and self._request.body_stream is not None:
706+
raise RuntimeError(
707+
"Cannot use write_data() on an HTTP/1.1 stream whose HttpRequest "
708+
"has a body_stream set. The H1 encoder is modal — it picks one "
709+
"body delivery path at init time and cannot switch mid-stream. "
710+
"Either remove the body_stream and use write_data() exclusively, "
711+
"or use the body_stream without calling write_data()."
712+
)
713+
return super().write_data(data_stream, end_stream)
714+
662715

663716
class Http2ClientStream(HttpClientStreamBase):
664717
__slots__ = ('_remote_end_stream_future',)
@@ -723,24 +776,34 @@ def activate(self) -> None:
723776
def write_data(self,
724777
data_stream: Union[InputStream, Any],
725778
end_stream: bool = False) -> "concurrent.futures.Future":
726-
'''Write a chunk of data to the request body stream.
779+
'''Write data to the HTTP/2 request body.
727780
728-
This method is only available when the stream was created with
729-
manual_write=True. This allows incremental writing of request data.
781+
The stream must have been created with ``manual_write=True`` and
782+
:meth:`activate()` must have been called before using this method.
730783
731-
Note: This method is inherited from the base class and works for both
732-
HTTP/1.1 and HTTP/2. It is kept here for backward compatibility.
784+
Unlike HTTP/1.1, HTTP/2 uses a queue-based write design
785+
(``outgoing_writes`` queue of ``aws_h2_stream_data_write`` structs).
786+
The body stream, if present, is simply the first item in the queue,
787+
and manual writes append additional items. The connection scheduler
788+
drains the queue and encodes DATA frames regardless of origin. This
789+
means HTTP/2 **can** combine a ``body_stream`` with subsequent
790+
``write_data()`` calls — the two compose naturally.
733791
734-
Args:
735-
data_stream (InputStream): Data to write. If not an InputStream,
736-
it will be wrapped in one. Can be None to send an empty chunk.
792+
This is a key design difference from HTTP/1.1, whose encoder is
793+
*modal* (picks one body path at init) rather than *compositional*.
737794
738-
end_stream (bool): True to indicate this is the last chunk and no more data
739-
will be sent. False if more chunks will follow.
795+
.. deprecated:: 0.x
796+
This method supersedes the C-level ``aws_http1_stream_write_chunk``
797+
API. Use ``write_data`` for all manual body writes on both HTTP/1.1
798+
and HTTP/2 streams.
799+
800+
Args:
801+
data_stream: Data to write. Wrapped in :class:`InputStream` if
802+
needed. ``None`` sends zero bytes.
803+
end_stream (bool): ``True`` if this is the last write.
740804
741805
Returns:
742-
concurrent.futures.Future: Future that completes when the write operation
743-
is done. The future will contain None on success, or an exception on failure.
806+
concurrent.futures.Future: Completes with ``None`` on success.
744807
'''
745808
return super().write_data(data_stream, end_stream)
746809

0 commit comments

Comments
 (0)