Skip to content

Commit 4b8546f

Browse files
azkrishpysbiscigl
andauthored
Unified write data API binding (#839)
Co-authored-by: sbiscigl <sbiscigl@amazon.com>
1 parent 94a24c7 commit 4b8546f

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

include/aws/crt/http/HttpConnection.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <aws/crt/Types.h>
1111
#include <aws/crt/io/Bootstrap.h>
1212
#include <aws/crt/io/SocketOptions.h>
13+
#include <aws/crt/io/Stream.h>
1314
#include <aws/crt/io/TlsOptions.h>
1415

1516
#include <functional>
@@ -118,6 +119,27 @@ namespace Aws
118119
* See `OnStreamComplete` for more info. This value can be empty.
119120
*/
120121
OnStreamComplete onStreamComplete;
122+
123+
/**
124+
* When true, request body data will be provided over time via `HttpClientStream::WriteData()`
125+
* The stream will only be polled for writing when data has been supplied.
126+
* When false (default), the entire request body is read from the input stream immediately.
127+
*
128+
* HTTP/1.1 requirements:
129+
* - SHOULD have either `Content-Length` OR `Transfer-Encoding: chunked` header (but not both).
130+
* Fails with AWS_ERROR_HTTP_INVALID_HEADER_FIELD if both are set.
131+
* Transfer-Encoding: chunked header will be automatically added if neither header is set.
132+
* - MUST NOT have a body stream set. Fails with AWS_ERROR_HTTP_INVALID_HEADER_FIELD otherwise.
133+
* - With `Content-Length`: total bytes written must exactly match the declared length.
134+
* Fails with AWS_ERROR_HTTP_OUTGOING_STREAM_LENGTH_INCORRECT if data exceeds Content-Length,
135+
* or if `end_stream` is set before enough data is written.
136+
* - With `Transfer-Encoding: chunked`: no length validation, data sent as chunks.
137+
*
138+
* HTTP/2: No `Content-Length` or `Transfer-Encoding` header required. Data sent via DATA frames.
139+
* Note: When this variable is set, we expect request to be ended with a data write with
140+
* end_stream=true.
141+
*/
142+
bool UseManualDataWrites = false;
121143
};
122144

123145
/**
@@ -191,6 +213,8 @@ namespace Aws
191213
std::shared_ptr<HttpStream> stream;
192214
};
193215

216+
using OnWriteDataComplete = std::function<void(std::shared_ptr<HttpStream> &stream, int errorCode)>;
217+
194218
/**
195219
* Subclass that represents an http client's view of an HttpStream.
196220
*/
@@ -216,6 +240,11 @@ namespace Aws
216240
*/
217241
bool Activate() noexcept;
218242

243+
int WriteData(
244+
std::shared_ptr<Aws::Crt::Io::InputStream> stream,
245+
const OnWriteDataComplete &onComplete,
246+
bool endStream = false) noexcept;
247+
219248
private:
220249
HttpClientStream(const std::shared_ptr<HttpClientConnection> &connection) noexcept;
221250

source/http/HttpConnection.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ namespace Aws
202202
options.on_response_headers = HttpStream::s_onIncomingHeaders;
203203
options.on_response_header_block_done = HttpStream::s_onIncomingHeaderBlockDone;
204204
options.on_complete = HttpStream::s_onStreamComplete;
205+
options.use_manual_data_writes = requestOptions.UseManualDataWrites;
205206

206207
/* Do the same ref counting trick we did with HttpClientConnection. We need to maintain a reference
207208
* internally (regardless of what the user does), until the Stream shuts down. */
@@ -361,6 +362,35 @@ namespace Aws
361362
return true;
362363
}
363364

365+
struct OnWriteUserData
366+
{
367+
Aws::Crt::Http::OnWriteDataComplete callback;
368+
Aws::Crt::Http::ClientStreamCallbackData callbackData;
369+
};
370+
371+
int HttpClientStream::WriteData(
372+
std::shared_ptr<Aws::Crt::Io::InputStream> stream,
373+
const OnWriteDataComplete &onComplete,
374+
bool endStream) noexcept
375+
{
376+
aws_http_stream_write_data_options options{};
377+
options.data = stream->GetUnderlyingStream();
378+
options.end_stream = endStream;
379+
options.on_complete = +[](struct aws_http_stream *, int error_code, void *user_data)
380+
{
381+
auto *userData = static_cast<OnWriteUserData *>(user_data);
382+
userData->callback(userData->callbackData.stream, error_code);
383+
Aws::Crt::Delete(userData, userData->callbackData.allocator);
384+
};
385+
386+
auto *data = Aws::Crt::New<OnWriteUserData>(m_callbackData.allocator);
387+
data->callback = onComplete;
388+
data->callbackData = m_callbackData;
389+
options.user_data = data;
390+
391+
return aws_http_stream_write_data(m_stream, &options);
392+
}
393+
364394
void HttpStream::UpdateWindow(std::size_t incrementSize) noexcept
365395
{
366396
aws_http_stream_update_window(m_stream, incrementSize);

0 commit comments

Comments
 (0)