Search in sources :

Example 6 with ApiContract

use of io.apiman.gateway.engine.beans.ApiContract in project apiman by apiman.

the class BucketFactory method bucketId.

/**
 * Creates the ID of the rate bucket to use.  The ID is composed differently
 * depending on the configuration of the policy.
 */
public String bucketId(RateLimitingConfig config, BucketIdBuilderContext context) {
    Api api = context.getApi();
    StringBuilder builder = new StringBuilder();
    // Public API in this branch
    if (context.getContract() == null) {
        // $NON-NLS-1$
        builder.append("PUBLIC||");
        // $NON-NLS-1$
        builder.append("||");
        builder.append(api.getOrganizationId());
        // $NON-NLS-1$
        builder.append("||");
        builder.append(api.getApiId());
        // $NON-NLS-1$
        builder.append("||");
        builder.append(api.getVersion());
        if (config.getGranularity() == RateLimitingGranularity.User) {
            String user = context.getUserSupplier().get();
            // $NON-NLS-1$
            builder.append("||");
            builder.append(user);
        } else if (config.getGranularity() == RateLimitingGranularity.Ip) {
            // $NON-NLS-1$
            builder.append("||");
            builder.append(context.getRemoteAddr());
        } else if (config.getGranularity() == RateLimitingGranularity.Api) {
        } else {
            return NO_CLIENT_AVAILABLE;
        }
    } else {
        // Have a fully valid contract in this branch.
        ApiContract contract = context.getContract();
        Client client = contract.getClient();
        String apiKey = client.getApiKey();
        builder.append(apiKey);
        if (config.getGranularity() == RateLimitingGranularity.User) {
            String user = context.getUserSupplier().get();
            if (user == null) {
                return NO_USER_AVAILABLE;
            } else {
                // $NON-NLS-1$
                builder.append("||USER||");
                builder.append(client.getOrganizationId());
                // $NON-NLS-1$
                builder.append("||");
                builder.append(client.getClientId());
                // $NON-NLS-1$
                builder.append("||");
                builder.append(user);
            }
        } else if (config.getGranularity() == RateLimitingGranularity.Client) {
            builder.append(apiKey);
            // $NON-NLS-1$
            builder.append("||APP||");
            builder.append(client.getOrganizationId());
            // $NON-NLS-1$
            builder.append("||");
            builder.append(client.getClientId());
        } else if (config.getGranularity() == RateLimitingGranularity.Ip) {
            builder.append(apiKey);
            // $NON-NLS-1$
            builder.append("||IP||");
            builder.append(client.getOrganizationId());
            // $NON-NLS-1$
            builder.append("||");
            builder.append(context.getRemoteAddr());
        } else {
            builder.append(apiKey);
            // $NON-NLS-1$
            builder.append("||SERVICE||");
            builder.append(api.getOrganizationId());
            // $NON-NLS-1$
            builder.append("||");
            builder.append(api.getApiId());
        }
    }
    return builder.toString();
}
Also used : Api(io.apiman.gateway.engine.beans.Api) Client(io.apiman.gateway.engine.beans.Client) ApiContract(io.apiman.gateway.engine.beans.ApiContract)

Example 7 with ApiContract

use of io.apiman.gateway.engine.beans.ApiContract in project apiman by apiman.

the class InMemoryRegistry method getContract.

/**
 * @see io.apiman.gateway.engine.IRegistry#getContract(java.lang.String, java.lang.String, java.lang.String, java.lang.String, io.apiman.gateway.engine.async.IAsyncResultHandler)
 */
@Override
public void getContract(String apiOrganizationId, String apiId, String apiVersion, String apiKey, IAsyncResultHandler<ApiContract> handler) {
    Client client = null;
    Api api = null;
    String apiIdx = getApiIndex(apiOrganizationId, apiId, apiVersion);
    synchronized (mutex) {
        client = (Client) getMap().get(apiKey);
        api = (Api) getMap().get(apiIdx);
    }
    if (client == null) {
        // $NON-NLS-1$
        Exception error = new ClientNotFoundException(Messages.i18n.format("InMemoryRegistry.NoClientForAPIKey", apiKey));
        handler.handle(AsyncResultImpl.create(error, ApiContract.class));
        return;
    }
    if (api == null) {
        Exception error = new ApiRetiredException(// $NON-NLS-1$
        Messages.i18n.format(// $NON-NLS-1$
        "InMemoryRegistry.ApiWasRetired", apiId, apiOrganizationId));
        handler.handle(AsyncResultImpl.create(error, ApiContract.class));
        return;
    }
    Contract matchedContract = null;
    for (Contract contract : client.getContracts()) {
        if (contract.matches(apiOrganizationId, apiId, apiVersion)) {
            matchedContract = contract;
            break;
        }
    }
    if (matchedContract == null) {
        Exception error = new NoContractFoundException(// $NON-NLS-1$
        Messages.i18n.format(// $NON-NLS-1$
        "InMemoryRegistry.NoContractFound", client.getClientId(), api.getApiId()));
        handler.handle(AsyncResultImpl.create(error, ApiContract.class));
        return;
    }
    ApiContract contract = new ApiContract(api, client, matchedContract.getPlan(), matchedContract.getPolicies());
    handler.handle(AsyncResultImpl.create(contract));
}
Also used : NoContractFoundException(io.apiman.gateway.engine.beans.exceptions.NoContractFoundException) ApiRetiredException(io.apiman.gateway.engine.beans.exceptions.ApiRetiredException) ClientNotFoundException(io.apiman.gateway.engine.beans.exceptions.ClientNotFoundException) Api(io.apiman.gateway.engine.beans.Api) Client(io.apiman.gateway.engine.beans.Client) Contract(io.apiman.gateway.engine.beans.Contract) ApiContract(io.apiman.gateway.engine.beans.ApiContract) RegistrationException(io.apiman.gateway.engine.beans.exceptions.RegistrationException) ClientNotFoundException(io.apiman.gateway.engine.beans.exceptions.ClientNotFoundException) ApiRetiredException(io.apiman.gateway.engine.beans.exceptions.ApiRetiredException) NoContractFoundException(io.apiman.gateway.engine.beans.exceptions.NoContractFoundException) ApiNotFoundException(io.apiman.gateway.engine.beans.exceptions.ApiNotFoundException) ApiContract(io.apiman.gateway.engine.beans.ApiContract)

Example 8 with ApiContract

use of io.apiman.gateway.engine.beans.ApiContract in project apiman by apiman.

the class RateLimitingPolicyTest method createTestContract.

/**
 * @return a test contract
 */
private ApiContract createTestContract() {
    Api api = new Api();
    api.setOrganizationId("ApiOrg");
    api.setApiId("Api");
    api.setVersion("1.0");
    Client app = new Client();
    app.setApiKey("12345");
    app.setOrganizationId("AppOrg");
    app.setClientId("App");
    app.setVersion("1.0");
    return new ApiContract(api, app, "Gold", null);
}
Also used : Api(io.apiman.gateway.engine.beans.Api) Client(io.apiman.gateway.engine.beans.Client) ApiContract(io.apiman.gateway.engine.beans.ApiContract)

Example 9 with ApiContract

use of io.apiman.gateway.engine.beans.ApiContract 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)

Example 10 with ApiContract

use of io.apiman.gateway.engine.beans.ApiContract in project apiman by apiman.

the class ApiRequestExecutorImpl method validateRequest.

/**
 * Validates that the contract being used for the request is valid against the
 * api information included in the request.  Basically the request includes
 * information indicating which specific api is being invoked.  This method
 * ensures that the api information in the contract matches the requested
 * api.
 * @param request the request to validate
 */
protected void validateRequest(ApiRequest request) throws InvalidContractException {
    ApiContract contract = request.getContract();
    boolean matches = true;
    if (!contract.getApi().getOrganizationId().equals(request.getApiOrgId())) {
        matches = false;
    }
    if (!contract.getApi().getApiId().equals(request.getApiId())) {
        matches = false;
    }
    if (!contract.getApi().getVersion().equals(request.getApiVersion())) {
        matches = false;
    }
    if (!matches) {
        throw new InvalidContractException(// $NON-NLS-1$
        Messages.i18n.format(// $NON-NLS-1$
        "EngineImpl.InvalidContractForApi", request.getApiOrgId(), request.getApiId(), request.getApiVersion()));
    }
}
Also used : InvalidContractException(io.apiman.gateway.engine.beans.exceptions.InvalidContractException) ApiContract(io.apiman.gateway.engine.beans.ApiContract)

Aggregations

ApiContract (io.apiman.gateway.engine.beans.ApiContract)10 Api (io.apiman.gateway.engine.beans.Api)8 Client (io.apiman.gateway.engine.beans.Client)8 Contract (io.apiman.gateway.engine.beans.Contract)6 ApiRetiredException (io.apiman.gateway.engine.beans.exceptions.ApiRetiredException)6 NoContractFoundException (io.apiman.gateway.engine.beans.exceptions.NoContractFoundException)6 ApiNotFoundException (io.apiman.gateway.engine.beans.exceptions.ApiNotFoundException)5 ClientNotFoundException (io.apiman.gateway.engine.beans.exceptions.ClientNotFoundException)5 RegistrationException (io.apiman.gateway.engine.beans.exceptions.RegistrationException)3 IOException (java.io.IOException)3 InvalidContractException (io.apiman.gateway.engine.beans.exceptions.InvalidContractException)2 PublishingException (io.apiman.gateway.engine.beans.exceptions.PublishingException)2 SQLException (java.sql.SQLException)2 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 IApiConnector (io.apiman.gateway.engine.IApiConnector)1 IConnectorConfig (io.apiman.gateway.engine.IConnectorConfig)1 IEngineResult (io.apiman.gateway.engine.IEngineResult)1 IAsyncResult (io.apiman.gateway.engine.async.IAsyncResult)1 IAsyncResultHandler (io.apiman.gateway.engine.async.IAsyncResultHandler)1 ApiRequest (io.apiman.gateway.engine.beans.ApiRequest)1