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();
}
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));
}
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);
}
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));
}
});
}
}
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()));
}
}
Aggregations