All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.policy.aws.lambda.LambdaInvoker Maven / Gradle / Ivy

/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gravitee.policy.aws.lambda;

import com.amazonaws.services.lambda.model.InvokeResult;
import io.gravitee.gateway.api.ExecutionContext;
import io.gravitee.gateway.api.Invoker;
import io.gravitee.gateway.api.buffer.Buffer;
import io.gravitee.gateway.api.handler.Handler;
import io.gravitee.gateway.api.http.HttpHeaderNames;
import io.gravitee.gateway.api.http.HttpHeaders;
import io.gravitee.gateway.api.proxy.ProxyConnection;
import io.gravitee.gateway.api.proxy.ProxyResponse;
import io.gravitee.gateway.api.stream.ReadStream;
import java.nio.ByteBuffer;

/**
 * Invoker allowing to delegate invocation to the specified invoker or replace the invocation response with the provided lambda respinse (aka {@link InvokeResult}).
 *
 * @author Jeoffrey HAEYAERT (jeoffrey.haeyaert at graviteesource.com)
 * @author GraviteeSource Team
 */
public class LambdaInvoker implements Invoker {

    private final Invoker delegate;
    private final boolean invokeDelegate;

    private InvokeResult invokeResult;

    LambdaInvoker(boolean invokeDelegate, Invoker delegate, InvokeResult invokeResult) {
        this.invokeDelegate = invokeDelegate;
        this.delegate = delegate;
        this.invokeResult = invokeResult;
    }

    public LambdaInvoker(boolean invokeDelegate, Invoker delegate) {
        this.invokeDelegate = invokeDelegate;
        this.delegate = delegate;
    }

    @Override
    public void invoke(ExecutionContext context, ReadStream stream, Handler connectionHandler) {
        // We have to skip the original invoker if isSendToConsumer is true
        if (!invokeDelegate) {
            // Replace the proxy response with the lambda response.
            final ProxyConnection proxyConnection = new LambdaProxyConnection();

            // Return connection to backend
            connectionHandler.handle(proxyConnection);

            // Plug underlying stream to connection stream
            stream.bodyHandler(proxyConnection::write).endHandler(aVoid -> proxyConnection.end());

            // Resume the incoming request to handle content and end
            context.request().resume();
        } else {
            delegate.invoke(context, stream, connectionHandler);
        }
    }

    public InvokeResult getInvokeResult() {
        return invokeResult;
    }

    public void setInvokeResult(InvokeResult invokeResult) {
        this.invokeResult = invokeResult;
    }

    class LambdaProxyConnection implements ProxyConnection {

        private Handler proxyResponseHandler;
        private Buffer content;

        LambdaProxyConnection() {}

        @Override
        public ProxyConnection write(Buffer chunk) {
            if (content == null) {
                content = Buffer.buffer();
            }
            content.appendBuffer(chunk);
            return this;
        }

        @Override
        public void end() {
            proxyResponseHandler.handle(new LambdaClientResponse());
        }

        @Override
        public ProxyConnection responseHandler(Handler responseHandler) {
            this.proxyResponseHandler = responseHandler;
            return this;
        }
    }

    class LambdaClientResponse implements ProxyResponse {

        private final HttpHeaders headers = HttpHeaders.create();

        private Handler bodyHandler;
        private Handler endHandler;

        LambdaClientResponse() {
            this.init();
        }

        private void init() {
            ByteBuffer payload = invokeResult.getPayload();

            if (payload != null) {
                headers.set(HttpHeaderNames.CONTENT_LENGTH, Integer.toString(payload.array().length));
            }
        }

        @Override
        public int status() {
            return invokeResult.getStatusCode();
        }

        @Override
        public HttpHeaders headers() {
            return headers;
        }

        @Override
        public ProxyResponse bodyHandler(Handler bodyHandler) {
            this.bodyHandler = bodyHandler;
            return this;
        }

        @Override
        public ProxyResponse endHandler(Handler endHandler) {
            this.endHandler = endHandler;
            return this;
        }

        @Override
        public ReadStream resume() {
            ByteBuffer payload = invokeResult.getPayload();

            if (payload != null) {
                bodyHandler.handle(Buffer.buffer(payload.array()));
            }

            endHandler.handle(null);
            return this;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy