You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I work on a gateway-type application built in Netty which proxies http requests to aws lambda. The gateway app signs the inbound http request using the awssdk 2.x before sending to lambda with a Netty http client.
Here is the code snippet:
//
// 1. inbound FullHttpRequest. content is a Netty ByteBuf
//
ByteBuf content = request.content();
//
// 2. Convert Netty ByteBuf to a type InvokeRequest accepts
//
byte[] arr;
if (buffer.hasArray()) {
arr = buffer.array();
} else {
arr = new byte[buffer.readableBytes()];
buffer.getBytes(buffer.readerIndex(), arr);
}
SdkBytes sdkBytes = SdkBytes.fromByteArray(arr); // always copy :(
buffer.release(); // fromByteArray always copy => release ByteBuf
//
// 3. sign request with AWS SDK v2
//
InvokeRequest invokeRequest =
InvokeRequest.builder()
.functionName(functionName)
.invocationType(InvocationType.REQUEST_RESPONSE)
.qualifier(qualifier)
.payload(sdkBytes)
.build();
AwsJsonProtocolFactory protocolFactory =
AwsJsonProtocolFactory.builder()
.clientConfiguration(
SdkClientConfiguration.builder()
.option(SdkClientOption.ENDPOINT, endpointUri)
.build())
.build();
InvokeRequestMarshaller invokeRequestMarshaller = new InvokeRequestMarshaller(protocolFactory);
SdkHttpFullRequest marshalledRequest = invokeRequestMarshaller.marshall(invokeRequest);
// looks thread-safe. TODO: get Amazon to officially confirm & document
Aws4Signer aws4Signer = Aws4Signer.create();
SdkHttpFullRequest signedRequest =
aws4Signer.sign(
marshalledRequest,
Aws4SignerParams.builder()
.awsCredentials(CREDENTIALS)
.signingName("lambda")
.signingRegion(AWS_REGION)
.timeOffset(0)
.build());
//
// 3. convert AWS signed request back into a Netty FullHttpRequest
// Another piece of work here that requires copying the signed request InputStream into a Netty ByteBuf
//
FullHttpRequest req = toNettyRequest(signedRequest);
/*
* private FullHttpRequest toNettyRequest(SdkHttpFullRequest awsReq) throws IOException {
* ByteBuf content;
* Optional<ContentStreamProvider> contentStreamProvider = awsReq.contentStreamProvider();
* // FIXME: copy InputStream directly into pooled ByteBuf
* if (contentStreamProvider.isPresent()) {
* byte[] contentBytes = IoUtils.toByteArray(contentStreamProvider.get().newStream());
* content = Unpooled.wrappedBuffer(contentBytes);
* } else {
* content = Unpooled.buffer(0);
* }
* ... etc.
*/
// 4. send signed FullHttpRequest to lambda with Netty client
myNettyClient.send(req);
With the current AWS SDK API, this implementation requires doing several copies of the request content ByteBuf/payload:
First to turn the Netty ByteBuf into a byte array
SdkBytes copies the byte array again
SdkBytes parent class (BytesWrapper) exposes methods that suggest more copies may happen depending on implementation of AWS SDK classes... (perhaps ContentStreamProvider is a copy of SdkBytes... I haven't checked...)
ContentStreamProvider's InputStream is copied in chunks to a byte[] in IoUtils.toByteArray.
The ByteArrayOutputStream (in IoUtils.toByteArray) gets resized (which causes copies) as more space is needed. InputStream.available() method is not used due to lack of clarity from the Java+AWS API (will it always return the full size of the underlying stream in this case?)
Request: I'd like this entire flow to be copy free and be able to reuse my allocated pooled Netty ByteBufs.
If InvokeRequest could accept an InputStream instead of a SdkBytes for its payload method, this would already be a great help as I would be able to wrap the Netty ByteBuf in a ByteBufInputStream. Underlying implementation of the request marshaller and signer would also need to be copy-free.
Alternatively, if I could sign the Netty request content without needing to create a SdkHttpFullRequest and just get the additional headers I need to add to the Netty request, this would make this entire flow simpler and more efficient.
The text was updated successfully, but these errors were encountered:
Uh oh!
There was an error while loading. Please reload this page.
I work on a gateway-type application built in Netty which proxies http requests to aws lambda. The gateway app signs the inbound http request using the awssdk 2.x before sending to lambda with a Netty http client.
Here is the code snippet:
With the current AWS SDK API, this implementation requires doing several copies of the request content ByteBuf/payload:
SdkBytes
copies the byte array againSdkBytes
parent class (BytesWrapper
) exposes methods that suggest more copies may happen depending on implementation of AWS SDK classes... (perhapsContentStreamProvider
is a copy ofSdkBytes
... I haven't checked...)ContentStreamProvider
'sInputStream
is copied in chunks to abyte[]
inIoUtils.toByteArray
.ByteArrayOutputStream
(inIoUtils.toByteArray
) gets resized (which causes copies) as more space is needed.InputStream.available()
method is not used due to lack of clarity from the Java+AWS API (will it always return the full size of the underlying stream in this case?)Request: I'd like this entire flow to be copy free and be able to reuse my allocated pooled Netty ByteBufs.
If
InvokeRequest
could accept an InputStream instead of aSdkBytes
for its payload method, this would already be a great help as I would be able to wrap the Netty ByteBuf in aByteBufInputStream
. Underlying implementation of the request marshaller and signer would also need to be copy-free.Alternatively, if I could sign the Netty request content without needing to create a
SdkHttpFullRequest
and just get the additional headers I need to add to the Netty request, this would make this entire flow simpler and more efficient.The text was updated successfully, but these errors were encountered: