Search in sources :

Example 26 with IApimanBuffer

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

the class EsCacheStoreComponent method getBinary.

/**
 * @see io.apiman.gateway.engine.components.ICacheStoreComponent#getBinary(java.lang.String, java.lang.Class, io.apiman.gateway.engine.async.IAsyncResultHandler)
 */
@Override
public <T> void getBinary(final String cacheKey, final Class<T> type, final IAsyncResultHandler<ISignalReadStream<T>> handler) {
    try {
        GetResponse response = getClient().get(new GetRequest(getFullIndexName()).id(cacheKey), RequestOptions.DEFAULT);
        // Did the GET succeed?  If not, return null.
        if (!response.isExists()) {
            handler.handle(AsyncResultImpl.create((ISignalReadStream<T>) null));
            return;
        }
        // Is the cache entry expired?  If so return null.
        String sourceAsString = response.getSourceAsString();
        CacheEntry cacheEntry = JSON_MAPPER.readValue(sourceAsString, CacheEntry.class);
        if (System.currentTimeMillis() > cacheEntry.getExpiresOn()) {
            // Cache item has expired.  Return null instead of the cached data.
            handler.handle(AsyncResultImpl.create((ISignalReadStream<T>) null));
            return;
        }
        try {
            final T head = (T) JSON_MAPPER.reader(type).readValue(cacheEntry.getHead());
            String b64Data = cacheEntry.getData();
            final IApimanBuffer data = bufferFactory.createBuffer(Base64.decodeBase64(b64Data));
            ISignalReadStream<T> rval = new ISignalReadStream<T>() {

                IAsyncHandler<IApimanBuffer> bodyHandler;

                IAsyncHandler<Void> endHandler;

                boolean finished = false;

                boolean aborted = false;

                @Override
                public void bodyHandler(IAsyncHandler<IApimanBuffer> bodyHandler) {
                    this.bodyHandler = bodyHandler;
                }

                @Override
                public void endHandler(IAsyncHandler<Void> endHandler) {
                    this.endHandler = endHandler;
                }

                @Override
                public T getHead() {
                    return head;
                }

                @Override
                public boolean isFinished() {
                    return finished;
                }

                @Override
                public void abort(Throwable t) {
                    finished = true;
                    aborted = true;
                }

                @Override
                public void transmit() {
                    if (!aborted) {
                        bodyHandler.handle(data);
                        endHandler.handle(null);
                    }
                    finished = true;
                }
            };
            handler.handle(AsyncResultImpl.create(rval));
        } catch (Throwable e) {
            LOGGER.error(e, "Error attempting to stream cached binary on key {0}", cacheKey);
            handler.handle(AsyncResultImpl.create((ISignalReadStream<T>) null));
        }
    } catch (Throwable e) {
        LOGGER.error(e, "Error attempting to GET cached binary on key {0}", cacheKey);
        handler.handle(AsyncResultImpl.create((ISignalReadStream<T>) null));
    }
}
Also used : IApimanBuffer(io.apiman.gateway.engine.io.IApimanBuffer) GetRequest(org.elasticsearch.action.get.GetRequest) ISignalReadStream(io.apiman.gateway.engine.io.ISignalReadStream) CacheEntry(io.apiman.gateway.engine.storage.model.CacheEntry) GetResponse(org.elasticsearch.action.get.GetResponse) IAsyncHandler(io.apiman.gateway.engine.async.IAsyncHandler)

Example 27 with IApimanBuffer

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

the class EsCacheStoreComponent method putBinary.

/**
 * @see io.apiman.gateway.engine.components.ICacheStoreComponent#putBinary(java.lang.String, java.lang.Object, long)
 */
@Override
public <T> ISignalWriteStream putBinary(final String cacheKey, final T jsonObject, final long timeToLive) throws IOException {
    final CacheEntry entry = new CacheEntry();
    entry.setExpiresOn(System.currentTimeMillis() + (timeToLive * 1000));
    entry.setHead(JSON_MAPPER.writeValueAsString(jsonObject));
    final IApimanBuffer data = bufferFactory.createBuffer();
    return new ISignalWriteStream() {

        boolean finished = false;

        boolean aborted = false;

        @Override
        public void abort(Throwable t) {
            finished = true;
            aborted = false;
        }

        @Override
        public boolean isFinished() {
            return finished;
        }

        @Override
        public void write(IApimanBuffer chunk) {
            data.append(chunk);
        }

        @Override
        public void end() {
            if (!aborted) {
                entry.setData(Base64.encodeBase64String(data.getBytes()));
                try {
                    IndexRequest indexRequest = new IndexRequest(getFullIndexName()).source(JSON_MAPPER.writeValueAsBytes(entry), XContentType.JSON).id(cacheKey);
                    getClient().index(indexRequest, RequestOptions.DEFAULT);
                } catch (Throwable e) {
                    LOGGER.error(e, "Unable to put binary at {0}. This should be non-fatal.", cacheKey);
                }
            }
            finished = true;
        }
    };
}
Also used : IApimanBuffer(io.apiman.gateway.engine.io.IApimanBuffer) CacheEntry(io.apiman.gateway.engine.storage.model.CacheEntry) ISignalWriteStream(io.apiman.gateway.engine.io.ISignalWriteStream) IndexRequest(org.elasticsearch.action.index.IndexRequest)

Example 28 with IApimanBuffer

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

the class URLRewritingStream method processBuffer.

/**
 * Scan the buffer for possible URLs.  As they are found, extract them from the buffer,
 * optionally translate them (only if they match the regular expression), and then
 * send along the translated version.  If a potential URL match is found but its end
 * spans the end of the buffer, just wait for the next chunk of data!
 */
private void processBuffer() {
    if (buffer == null || buffer.length() == 0) {
        return;
    }
    position = 0;
    int maxPos = buffer.length() - 1;
    boolean done = false;
    IApimanBuffer originalBuffer = buffer;
    int bytesConsumed = 0;
    int preUrlFromPos = 0;
    int urlsFound = 0;
    while (!done) {
        if (originalBuffer.get(position) == (byte) 'h' || originalBuffer.get(position) == (byte) 'H') {
            if (isURLStart()) {
                urlsFound++;
                // Write everything up to this point - consider it "consumed"
                if (position > 0) {
                    IApimanBuffer preUrlData = bufferFactory.createBuffer(originalBuffer.getBytes(preUrlFromPos, position));
                    super.write(preUrlData);
                    bytesConsumed = position;
                }
                // Now consume the URL
                int originalPos = position;
                String url = consumeURL();
                // the end of the chunk and need to wait for more data
                if (url != null) {
                    url = rewriteURL(url);
                    IApimanBuffer urlBuffer;
                    if (url != null) {
                        // $NON-NLS-1$
                        urlBuffer = bufferFactory.createBuffer(url, "UTF-8");
                    } else {
                        urlBuffer = bufferFactory.createBuffer(originalBuffer.getBytes(originalPos, position));
                    }
                    super.write(urlBuffer);
                    bytesConsumed = position;
                    preUrlFromPos = position;
                } else {
                    done = true;
                }
            } else {
                position++;
            }
        } else {
            position++;
        }
        if (position > maxPos) {
            done = true;
        }
    }
    // What do we do with what's left?  If there *is* anything left!
    if (urlsFound == 0) {
        super.write(originalBuffer);
        buffer = null;
    } else {
        buffer = bufferFactory.createBuffer(originalBuffer.getBytes(bytesConsumed, maxPos + 1));
        if (atEnd) {
            super.write(buffer);
        }
    }
}
Also used : IApimanBuffer(io.apiman.gateway.engine.io.IApimanBuffer)

Example 29 with IApimanBuffer

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

the class InfinispanCacheStoreComponent method putBinary.

/**
 * @see io.apiman.gateway.engine.components.ICacheStoreComponent#putBinary(java.lang.String, java.lang.Object, long)
 */
@Override
public <T> ISignalWriteStream putBinary(final String cacheKey, final T jsonObject, final long timeToLive) throws IOException {
    final IApimanBuffer dataBuffer = bufferFactory.createBuffer(0);
    return new ISignalWriteStream() {

        private boolean finished = false;

        private boolean aborted = false;

        @Override
        public void abort(Throwable t) {
            aborted = true;
            finished = false;
        }

        @Override
        public boolean isFinished() {
            return finished;
        }

        @Override
        public void write(IApimanBuffer chunk) {
            dataBuffer.append(chunk);
        }

        @Override
        public void end() {
            if (!aborted) {
                synchronized (mutex) {
                    InfinispanCacheEntry entry = (InfinispanCacheEntry) getCache().get(cacheKey);
                    if (entry == null) {
                        entry = new InfinispanCacheEntry();
                    }
                    entry.setHead(jsonObject);
                    entry.setExpiresOn(System.currentTimeMillis() + (timeToLive * 1000));
                    entry.setData(dataBuffer.getBytes());
                    getCache().put(cacheKey, entry);
                }
            }
        }
    };
}
Also used : IApimanBuffer(io.apiman.gateway.engine.io.IApimanBuffer) ISignalWriteStream(io.apiman.gateway.engine.io.ISignalWriteStream)

Example 30 with IApimanBuffer

use of io.apiman.gateway.engine.io.IApimanBuffer 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

IApimanBuffer (io.apiman.gateway.engine.io.IApimanBuffer)31 ByteBuffer (io.apiman.gateway.engine.io.ByteBuffer)12 ISignalWriteStream (io.apiman.gateway.engine.io.ISignalWriteStream)11 Test (org.junit.Test)11 ApiRequest (io.apiman.gateway.engine.beans.ApiRequest)7 ApiResponse (io.apiman.gateway.engine.beans.ApiResponse)7 AbstractStream (io.apiman.gateway.engine.io.AbstractStream)6 IAsyncHandler (io.apiman.gateway.engine.async.IAsyncHandler)5 IEngineResult (io.apiman.gateway.engine.IEngineResult)4 IBufferFactoryComponent (io.apiman.gateway.engine.components.IBufferFactoryComponent)4 ISignalReadStream (io.apiman.gateway.engine.io.ISignalReadStream)4 IApiRequestExecutor (io.apiman.gateway.engine.IApiRequestExecutor)3 IAsyncResultHandler (io.apiman.gateway.engine.async.IAsyncResultHandler)3 CacheEntry (io.apiman.gateway.engine.storage.model.CacheEntry)3 IOException (java.io.IOException)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)3 IApiConnector (io.apiman.gateway.engine.IApiConnector)2 IConnectorConfig (io.apiman.gateway.engine.IConnectorConfig)2 IEngine (io.apiman.gateway.engine.IEngine)2 IAsyncResult (io.apiman.gateway.engine.async.IAsyncResult)2