@@ -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
663716class 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