Search in sources :

Example 1 with IConnectorConfig

use of io.apiman.gateway.engine.IConnectorConfig in project apiman by apiman.

the class DefaultEngineFactoryTest method testCreateEngine.

/**
 * Test method for {@link io.apiman.gateway.engine.impl.AbstractEngineFactory#createEngine()}.
 * @throws ExecutionException
 * @throws InterruptedException
 */
@Test
public void testCreateEngine() throws InterruptedException, ExecutionException {
    DefaultEngineFactory factory = new DefaultEngineFactory() {

        @Override
        protected IComponentRegistry createComponentRegistry(IPluginRegistry pluginRegistry) {
            return new DefaultComponentRegistry() {

                @Override
                protected void registerBufferFactoryComponent() {
                    addComponent(IBufferFactoryComponent.class, new ByteBufferFactoryComponent());
                }
            };
        }

        @Override
        protected IConnectorFactory createConnectorFactory(IPluginRegistry pluginRegistry) {
            return new IConnectorFactory() {

                @Override
                public IApiConnector createConnector(ApiRequest request, Api api, RequiredAuthType requiredAuthType, boolean hasDataPolicy, IConnectorConfig connectorConfig) {
                    Assert.assertEquals("test", api.getEndpointType());
                    Assert.assertEquals("test:endpoint", api.getEndpoint());
                    IApiConnector connector = new IApiConnector() {

                        /**
                         * @see io.apiman.gateway.engine.IApiConnector#connect(io.apiman.gateway.engine.beans.ApiRequest, io.apiman.gateway.engine.async.IAsyncResultHandler)
                         */
                        @Override
                        public IApiConnection connect(ApiRequest request, IAsyncResultHandler<IApiConnectionResponse> handler) throws ConnectorException {
                            final ApiResponse response = new ApiResponse();
                            response.setCode(200);
                            // $NON-NLS-1$
                            response.setMessage("OK");
                            mockApiConnectionResponse = new MockApiConnectionResponse() {

                                @Override
                                public void write(IApimanBuffer chunk) {
                                    handleBody(chunk);
                                }

                                @Override
                                protected void handleHead(ApiResponse head) {
                                    return;
                                }

                                @Override
                                public ApiResponse getHead() {
                                    return response;
                                }

                                @Override
                                public void end() {
                                    handleEnd();
                                }

                                @Override
                                public void transmit() {
                                    transmitHandler.handle((Void) null);
                                }

                                @Override
                                public void abort(Throwable t) {
                                }
                            };
                            IAsyncResult<IApiConnectionResponse> mockResponseResultHandler = mock(IAsyncResult.class);
                            given(mockResponseResultHandler.isSuccess()).willReturn(true);
                            given(mockResponseResultHandler.isError()).willReturn(false);
                            given(mockResponseResultHandler.getResult()).willReturn(mockApiConnectionResponse);
                            mockApiConnection = mock(MockApiConnection.class);
                            given(mockApiConnection.getHead()).willReturn(request);
                            // Handle head
                            handler.handle(mockResponseResultHandler);
                            return mockApiConnection;
                        }
                    };
                    return connector;
                }

                @Override
                public IConnectorConfig createConnectorConfig(ApiRequest request, Api api) {
                    return new TestConnectorConfigImpl();
                }
            };
        }

        @Override
        protected IDelegateFactory createLoggerFactory(IPluginRegistry pluginRegistry) {
            return null;
        }

        @Override
        protected IApiRequestPathParser createRequestPathParser(IPluginRegistry pluginRegistry) {
            return new DefaultRequestPathParser(null);
        }

        @Override
        protected void complete() {
        }
    };
    IEngine engine = factory.createEngine();
    Assert.assertNotNull(engine);
    // create a api
    Api api = new Api();
    api.setEndpointType("test");
    api.setEndpoint("test:endpoint");
    api.setOrganizationId("TestOrg");
    api.setApiId("TestApi");
    api.setVersion("1.0");
    // create a client
    Client app = new Client();
    app.setClientId("TestApp");
    app.setOrganizationId("TestOrg");
    app.setVersion("1.0");
    app.setApiKey("client-12345");
    Contract contract = new Contract();
    contract.setPlan("Gold");
    contract.setApiId("TestApi");
    contract.setApiOrgId("TestOrg");
    contract.setApiVersion("1.0");
    contract.setPolicies(policyList);
    app.addContract(contract);
    // simple api/app config
    engine.getRegistry().publishApi(api, new IAsyncResultHandler<Void>() {

        @Override
        public void handle(IAsyncResult<Void> result) {
        }
    });
    engine.getRegistry().registerClient(app, new IAsyncResultHandler<Void>() {

        @Override
        public void handle(IAsyncResult<Void> result) {
        }
    });
    ApiRequest request = new ApiRequest();
    request.setApiKey("client-12345");
    request.setApiId("TestApi");
    request.setApiOrgId("TestOrg");
    request.setApiVersion("1.0");
    request.setDestination("/");
    request.setUrl("http://localhost:9999/");
    request.setType("TEST");
    IApiRequestExecutor prExecutor = engine.executor(request, new IAsyncResultHandler<IEngineResult>() {

        // At this point, we are either saying *fail* or *response connection is ready*
        @Override
        public void handle(IAsyncResult<IEngineResult> result) {
            IEngineResult er = result.getResult();
            // No exception occurred
            Assert.assertTrue(result.isSuccess());
            // The chain evaluation succeeded
            Assert.assertNotNull(er);
            Assert.assertTrue(!er.isFailure());
            Assert.assertNotNull(er.getApiResponse());
            // $NON-NLS-1$
            Assert.assertEquals("OK", er.getApiResponse().getMessage());
            er.bodyHandler(mockBodyHandler);
            er.endHandler(mockEndHandler);
        }
    });
    prExecutor.streamHandler(new IAsyncHandler<ISignalWriteStream>() {

        @Override
        public void handle(ISignalWriteStream streamWriter) {
            streamWriter.write(mockBufferInbound);
            streamWriter.end();
        }
    });
    transmitHandler = new IAsyncHandler<Void>() {

        @Override
        public void handle(Void result) {
            // NB: This is cheating slightly for testing purposes, we don't have real async here.
            // Only now start writing stuff, so user has had opportunity to set handlers
            mockApiConnectionResponse.write(mockBufferOutbound);
            mockApiConnectionResponse.end();
        }
    };
    prExecutor.execute();
    // Request handler should receive the mock inbound buffer once only
    verify(mockApiConnection, times(1)).write(mockBufferInbound);
    // Ultimately user should receive the contrived response and end in order.
    InOrder order = inOrder(mockBodyHandler, mockEndHandler);
    order.verify(mockBodyHandler).handle(mockBufferOutbound);
    order.verify(mockEndHandler).handle((Void) null);
}
Also used : IApimanBuffer(io.apiman.gateway.engine.io.IApimanBuffer) IEngineResult(io.apiman.gateway.engine.IEngineResult) IEngine(io.apiman.gateway.engine.IEngine) IAsyncResultHandler(io.apiman.gateway.engine.async.IAsyncResultHandler) ApiRequest(io.apiman.gateway.engine.beans.ApiRequest) IApiConnectionResponse(io.apiman.gateway.engine.IApiConnectionResponse) ApiResponse(io.apiman.gateway.engine.beans.ApiResponse) RequiredAuthType(io.apiman.gateway.engine.auth.RequiredAuthType) IConnectorFactory(io.apiman.gateway.engine.IConnectorFactory) Client(io.apiman.gateway.engine.beans.Client) IApiRequestExecutor(io.apiman.gateway.engine.IApiRequestExecutor) IPluginRegistry(io.apiman.gateway.engine.IPluginRegistry) InOrder(org.mockito.InOrder) IConnectorConfig(io.apiman.gateway.engine.IConnectorConfig) ISignalWriteStream(io.apiman.gateway.engine.io.ISignalWriteStream) IApiConnector(io.apiman.gateway.engine.IApiConnector) Api(io.apiman.gateway.engine.beans.Api) Contract(io.apiman.gateway.engine.beans.Contract) Test(org.junit.Test)

Example 2 with IConnectorConfig

use of io.apiman.gateway.engine.IConnectorConfig in project apiman by apiman.

the class ApiRequestExecutorImpl method execute.

/**
 * @see io.apiman.gateway.engine.IApiRequestExecutor#execute()
 */
@Override
public void execute() {
    // load the api data based on request
    registry.getApi(request.getApiOrgId(), request.getApiId(), request.getApiVersion(), (IAsyncResult<Api> apiResult) -> {
        if (apiResult.isSuccess()) {
            api = apiResult.getResult();
        } else if (apiResult.isError()) {
            resultHandler.handle(AsyncResultImpl.create(apiResult.getError(), IEngineResult.class));
        }
    });
    // check if api disable key are enabled
    if (api != null && !api.isKeysStrippingDisabled()) {
        // Strip apikey
        stripApiKey();
    }
    // Fill out some of the basic metrics structure.
    requestMetric.setRequestStart(new Date());
    requestMetric.setUrl(request.getUrl());
    requestMetric.setResource(request.getDestination());
    requestMetric.setMethod(request.getType());
    requestMetric.setApiOrgId(request.getApiOrgId());
    requestMetric.setApiId(request.getApiId());
    requestMetric.setApiVersion(request.getApiVersion());
    // Set request metric
    context.setAttribute(PolicyContextKeys.REQUEST_METRIC, requestMetric);
    // Set connector config early (allows mutation of certain connector properties)
    IConnectorConfig connectorConfig = connectorFactory.createConnectorConfig(request, api);
    context.setConnectorConfiguration(connectorConfig);
    // Create the handler that will be called once the policies are asynchronously
    // loaded (can happen this way due to the plugin framework).
    final IAsyncHandler<List<PolicyWithConfiguration>> policiesLoadedHandler = (List<PolicyWithConfiguration> result) -> {
        policyImpls = result;
        // Set up the policy chain request, call #doApply to execute.
        requestChain = createRequestChain((ApiRequest req) -> {
            IConnectorInterceptor connectorInterceptor = context.getConnectorInterceptor();
            IApiConnector connector;
            if (connectorInterceptor == null) {
                connector = connectorFactory.createConnector(req, api, RequiredAuthType.parseType(api), hasDataPolicy, connectorConfig);
            } else {
                connector = connectorInterceptor.createConnector();
            }
            // TODO check for a null connector
            // Open up a connection to the back-end if we're given the OK from the request chain
            requestMetric.setApiStart(new Date());
            // Attach the response handler here.
            apiConnection = connector.connect(req, createApiConnectionResponseHandler());
            // Write the body chunks from the *policy request* into the connector request.
            requestChain.bodyHandler(buffer -> {
                requestMetric.setBytesUploaded(requestMetric.getBytesUploaded() + buffer.length());
                apiConnection.write(buffer);
            });
            // Indicate end from policy chain request to connector request.
            requestChain.endHandler(onEnd -> apiConnection.end());
            // Once we have returned from connector.request, we know it is safe to start
            // writing chunks without buffering. At this point, it is the responsibility
            // of the implementation as to how they should cope with the chunks.
            handleStream();
        });
        requestChain.doApply(request);
    };
    // The handler used when we need to parse the inbound request payload into
    // an object and make it available via the policy context.
    final IAsyncResultHandler<Object> payloadParserHandler = new IAsyncResultHandler<Object>() {

        @Override
        public void handle(IAsyncResult<Object> result) {
            if (result.isSuccess()) {
                final Object payload = result.getResult();
                // Store the parsed object in the policy context.
                context.setAttribute(PolicyContextKeys.REQUEST_PAYLOAD, payload);
                context.setAttribute(PolicyContextKeys.REQUEST_PAYLOAD_IO, payloadIO);
                // Now replace the inbound stream handler with one that uses the payload IO
                // object to re-marshall the (possibly modified) payload object to bytes
                // and sends that (because the *real* inbound stream has already been consumed)
                streamHandler(new IAsyncHandler<ISignalWriteStream>() {

                    @Override
                    public void handle(ISignalWriteStream connectorStream) {
                        try {
                            if (payload == null) {
                                connectorStream.end();
                            } else {
                                payloadIO = context.getAttribute(PolicyContextKeys.REQUEST_PAYLOAD_IO, payloadIO);
                                byte[] data = payloadIO.marshall(payload);
                                IApimanBuffer buffer = bufferFactory.createBuffer(data);
                                connectorStream.write(buffer);
                                connectorStream.end();
                            }
                        } catch (Exception e) {
                            connectorStream.abort(e);
                            throw new RuntimeException(e);
                        }
                    }
                });
                // Load and executes the policies
                loadPolicies(policiesLoadedHandler);
            } else {
                resultHandler.handle(AsyncResultImpl.create(result.getError(), IEngineResult.class));
            }
        }
    };
    // then we lookup the Contract and use that.
    if (request.getApiKey() == null || (api != null && api.isKeysStrippingDisabled())) {
        if (api == null) {
            // $NON-NLS-1$
            ApiNotFoundException error = new ApiNotFoundException(Messages.i18n.format("EngineImpl.ApiNotFound"));
            resultHandler.handle(AsyncResultImpl.create(error, IEngineResult.class));
        } else if (!api.isPublicAPI()) {
            // $NON-NLS-1$
            InvalidApiException error = new InvalidApiException(Messages.i18n.format("EngineImpl.ApiNotPublic"));
            // Forbidden
            error.setStatusCode(403);
            resultHandler.handle(AsyncResultImpl.create(error, IEngineResult.class));
        } else {
            resolvePropertyReplacements(api);
            request.setApi(api);
            policies = api.getApiPolicies();
            policyImpls = new ArrayList<>(policies.size());
            // or a JSON document
            if (api.isParsePayload()) {
                parsePayload(payloadParserHandler);
            } else {
                loadPolicies(policiesLoadedHandler);
            }
        }
    } else {
        String apiOrgId = request.getApiOrgId();
        String apiId = request.getApiId();
        String apiVersion = request.getApiVersion();
        String apiKey = request.getApiKey();
        registry.getContract(apiOrgId, apiId, apiVersion, apiKey, (IAsyncResult<ApiContract> contractResult) -> {
            if (contractResult.isSuccess()) {
                ApiContract apiContract = contractResult.getResult();
                resolvePropertyReplacements(apiContract);
                requestMetric.setClientOrgId(apiContract.getClient().getOrganizationId());
                requestMetric.setClientId(apiContract.getClient().getClientId());
                requestMetric.setClientVersion(apiContract.getClient().getVersion());
                requestMetric.setPlanId(apiContract.getPlan());
                requestMetric.setContractId(request.getApiKey());
                api = apiContract.getApi();
                request.setContract(apiContract);
                request.setApi(api);
                policies = apiContract.getPolicies();
                policyImpls = new ArrayList<>(policies.size());
                if (request.getApiOrgId() != null) {
                    try {
                        validateRequest(request);
                    } catch (InvalidContractException e) {
                        resultHandler.handle(AsyncResultImpl.create(e, IEngineResult.class));
                        return;
                    }
                }
                // or a JSON document
                if (api.isParsePayload()) {
                    parsePayload(payloadParserHandler);
                } else {
                    // Load and executes the policies
                    loadPolicies(policiesLoadedHandler);
                }
            } else {
                resultHandler.handle(AsyncResultImpl.create(contractResult.getError(), IEngineResult.class));
            }
        });
    }
}
Also used : IApimanBuffer(io.apiman.gateway.engine.io.IApimanBuffer) IEngineResult(io.apiman.gateway.engine.IEngineResult) ApiNotFoundException(io.apiman.gateway.engine.beans.exceptions.ApiNotFoundException) ArrayList(java.util.ArrayList) IAsyncResultHandler(io.apiman.gateway.engine.async.IAsyncResultHandler) ApiRequest(io.apiman.gateway.engine.beans.ApiRequest) InvalidApiException(io.apiman.gateway.engine.beans.exceptions.InvalidApiException) List(java.util.List) ArrayList(java.util.ArrayList) InvalidContractException(io.apiman.gateway.engine.beans.exceptions.InvalidContractException) IConnectorConfig(io.apiman.gateway.engine.IConnectorConfig) ISignalWriteStream(io.apiman.gateway.engine.io.ISignalWriteStream) IApiConnector(io.apiman.gateway.engine.IApiConnector) Date(java.util.Date) RequestAbortedException(io.apiman.gateway.engine.beans.exceptions.RequestAbortedException) InvalidApiException(io.apiman.gateway.engine.beans.exceptions.InvalidApiException) InvalidContractException(io.apiman.gateway.engine.beans.exceptions.InvalidContractException) ApiNotFoundException(io.apiman.gateway.engine.beans.exceptions.ApiNotFoundException) IConnectorInterceptor(io.apiman.gateway.engine.policy.IConnectorInterceptor) IAsyncResult(io.apiman.gateway.engine.async.IAsyncResult) PolicyWithConfiguration(io.apiman.gateway.engine.policy.PolicyWithConfiguration) ApiContract(io.apiman.gateway.engine.beans.ApiContract)

Aggregations

IApiConnector (io.apiman.gateway.engine.IApiConnector)2 IConnectorConfig (io.apiman.gateway.engine.IConnectorConfig)2 IEngineResult (io.apiman.gateway.engine.IEngineResult)2 IAsyncResultHandler (io.apiman.gateway.engine.async.IAsyncResultHandler)2 ApiRequest (io.apiman.gateway.engine.beans.ApiRequest)2 IApimanBuffer (io.apiman.gateway.engine.io.IApimanBuffer)2 ISignalWriteStream (io.apiman.gateway.engine.io.ISignalWriteStream)2 IApiConnectionResponse (io.apiman.gateway.engine.IApiConnectionResponse)1 IApiRequestExecutor (io.apiman.gateway.engine.IApiRequestExecutor)1 IConnectorFactory (io.apiman.gateway.engine.IConnectorFactory)1 IEngine (io.apiman.gateway.engine.IEngine)1 IPluginRegistry (io.apiman.gateway.engine.IPluginRegistry)1 IAsyncResult (io.apiman.gateway.engine.async.IAsyncResult)1 RequiredAuthType (io.apiman.gateway.engine.auth.RequiredAuthType)1 Api (io.apiman.gateway.engine.beans.Api)1 ApiContract (io.apiman.gateway.engine.beans.ApiContract)1 ApiResponse (io.apiman.gateway.engine.beans.ApiResponse)1 Client (io.apiman.gateway.engine.beans.Client)1 Contract (io.apiman.gateway.engine.beans.Contract)1 ApiNotFoundException (io.apiman.gateway.engine.beans.exceptions.ApiNotFoundException)1