blob: e0fd6c9a196b694d2ddb93d56bccec20275fcc66 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.synapse.mediators.throttle;
import junit.framework.TestCase;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMDocument;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseException;
import org.apache.synapse.config.Entry;
import org.apache.synapse.config.SynapseConfiguration;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.core.axis2.Axis2SynapseEnvironment;
import org.apache.synapse.mediators.AbstractMediator;
import org.wso2.throttle.*;
import java.io.StringReader;
/**
* Throttle Mediator Test - This class test throttling when policy has specified as both of
* InLine and a registry key
*/
public class ThrottleMediatorTest extends TestCase {
private static final String REMOTE_ADDR = "Remote_Addr";
private static final String POLICY = " <wsp:Policy xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\"\n" +
" xmlns:throttle=\"http://www.wso2.org/products/wso2commons/throttle\">\n" +
" <throttle:ThrottleAssertion>\n" +
" <wsp:All>\n" +
" <throttle:ID throttle:type=\"IP\">other</throttle:ID>\n" +
" <wsp:ExactlyOne>\n" +
" <wsp:All>\n" +
" <throttle:MaximumCount>8</throttle:MaximumCount>\n" +
" <throttle:UnitTime>800000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\">10</throttle:ProhibitTimePeriod>\n" +
" </wsp:All>\n" +
" </wsp:ExactlyOne>\n" +
" </wsp:All>\n" +
" <wsp:All>\n" +
" <throttle:ID throttle:type=\"IP\">192.168.8.200-192.168.8.222</throttle:ID>\n" +
" <wsp:ExactlyOne>\n" +
" <wsp:All>\n" +
" <throttle:MaximumCount>3</throttle:MaximumCount>\n" +
" <throttle:UnitTime>800000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\">10000</throttle:ProhibitTimePeriod>\n" +
" </wsp:All>\n" +
" </wsp:ExactlyOne>\n" +
" </wsp:All>\n" +
" <wsp:All>\n" +
" <throttle:ID throttle:type=\"IP\">192.168.8.201</throttle:ID>\n" +
" <wsp:ExactlyOne>\n" +
" <wsp:All>\n" +
" <throttle:MaximumCount>200</throttle:MaximumCount>\n" +
" <throttle:UnitTime>600000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\"></throttle:ProhibitTimePeriod>\n" +
" </wsp:All>\n" +
" </wsp:ExactlyOne>\n" +
" </wsp:All>\n" +
" <wsp:All>\n" +
" <throttle:ID throttle:type=\"IP\">192.168.8.198</throttle:ID>\n" +
" <wsp:ExactlyOne>\n" +
" <wsp:All>\n" +
" <throttle:MaximumCount>50</throttle:MaximumCount>\n" +
" <throttle:UnitTime>500000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\"></throttle:ProhibitTimePeriod>\n" +
" </wsp:All>\n" +
" </wsp:ExactlyOne>\n" +
" </wsp:All>\n" +
" </throttle:ThrottleAssertion>\n" +
" </wsp:Policy>";
private static final String NEW_POLICY = "<wsp:Policy xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\"\n" +
" xmlns:throttle=\"http://www.wso2.org/products/wso2commons/throttle\">\n" +
"<throttle:MediatorThrottleAssertion>\n" +
" <throttle:MaximumConcurrentAccess>10</throttle:MaximumConcurrentAccess>\n" +
" <wsp:Policy>\n" +
" <throttle:ID throttle:type=\"IP\">other</throttle:ID>\n" +
" <wsp:Policy>\n" +
" <throttle:Control>\n" +
" <wsp:Policy>\n" +
" <throttle:MaximumCount>8</throttle:MaximumCount>\n" +
" <throttle:UnitTime>800000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\">10\n" +
" </throttle:ProhibitTimePeriod>\n" +
" </wsp:Policy>\n" +
" </throttle:Control>\n" +
" </wsp:Policy>\n" +
" </wsp:Policy>\n" +
" <wsp:Policy>\n" +
" <throttle:ID throttle:type=\"IP\">192.168.8.200-192.168.8.222</throttle:ID>\n" +
" <wsp:Policy>\n" +
" <throttle:Control>\n" +
" <wsp:Policy>\n" +
" <throttle:MaximumCount>3</throttle:MaximumCount>\n" +
" <throttle:UnitTime>800000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\">10000\n" +
" </throttle:ProhibitTimePeriod>\n" +
" </wsp:Policy>\n" +
" </throttle:Control>\n" +
" </wsp:Policy>\n" +
" </wsp:Policy>\n" +
" <wsp:Policy>\n" +
" <throttle:ID throttle:type=\"IP\">192.168.8.201</throttle:ID>\n" +
" <wsp:Policy>\n" +
" <throttle:Control>\n" +
" <wsp:Policy>\n" +
" <throttle:MaximumCount>200</throttle:MaximumCount>\n" +
" <throttle:UnitTime>600000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\"></throttle:ProhibitTimePeriod>\n" +
" </wsp:Policy>\n" +
" </throttle:Control>\n" +
" </wsp:Policy>\n" +
" </wsp:Policy>\n" +
" <wsp:Policy>\n" +
" <throttle:ID throttle:type=\"IP\">192.168.8.198</throttle:ID>\n" +
" <wsp:Policy>\n" +
" <throttle:Control>\n" +
" <wsp:Policy>\n" +
" <throttle:MaximumCount>50</throttle:MaximumCount>\n" +
" <throttle:UnitTime>500000</throttle:UnitTime>\n" +
" <throttle:ProhibitTimePeriod wsp:Optional=\"true\"></throttle:ProhibitTimePeriod>\n" +
" </wsp:Policy>\n" +
" </throttle:Control>\n" +
" </wsp:Policy>\n" +
" </wsp:Policy>\n" +
"</throttle:MediatorThrottleAssertion>\n" +
"</wsp:Policy>";
public ThrottleMediatorTest() {
super(ThrottleMediatorTest.class.getName());
}
public static MessageContext createLightweightSynapseMessageContext(
String payload) throws Exception {
org.apache.axis2.context.MessageContext mc =
new org.apache.axis2.context.MessageContext();
SynapseConfiguration config = new SynapseConfiguration();
SynapseEnvironment env = new Axis2SynapseEnvironment(config);
MessageContext synMc = new Axis2MessageContext(mc, config, env);
SOAPEnvelope envelope =
OMAbstractFactory.getSOAP11Factory().getDefaultEnvelope();
OMDocument omDoc =
OMAbstractFactory.getSOAP11Factory().createOMDocument();
omDoc.addChild(envelope);
envelope.getBody().addChild(OMXMLBuilderFactory.createOMBuilder(new StringReader(payload)).getDocumentElement());
synMc.setEnvelope(envelope);
return synMc;
}
public void testMediate() throws Exception {
OMXMLParserWrapper builder = OMXMLBuilderFactory.createOMBuilder(new StringReader(POLICY));
ThrottleTestMediator throttleMediator = new ThrottleTestMediator();
throttleMediator.setPolicyKey("throttlepolicy");
MessageContext synCtx = createLightweightSynapseMessageContext("<empty/>");
synCtx.setProperty(REMOTE_ADDR, "192.168.8.212");
SynapseConfiguration synCfg = new SynapseConfiguration();
Entry prop = new Entry();
prop.setKey("throttlepolicy");
prop.setType(Entry.INLINE_XML);
prop.setValue(builder.getDocumentElement());
synCfg.addEntry("throttlepolicy", prop);
synCtx.setConfiguration(synCfg);
for (int i = 0; i < 6; i++) {
try {
throttleMediator.mediate(synCtx);
Thread.sleep(1000);
}
catch (Exception e) {
if (i == 3) {
assertTrue(e.getMessage().lastIndexOf("IP_BASE") > 0);
}
if (i == 4) {
assertTrue(e.getMessage().lastIndexOf("IP_BASE") > 0);
}
if (i == 5) {
assertTrue(e.getMessage().lastIndexOf("IP_BASE") > 0);
}
}
}
}
public void testMediateWithInLineXML() throws Exception {
OMXMLParserWrapper builder = OMXMLBuilderFactory.createOMBuilder(new StringReader(POLICY));
ThrottleTestMediator throttleMediator = new ThrottleTestMediator();
throttleMediator.setInLinePolicy(builder.getDocumentElement());
MessageContext synCtx = createLightweightSynapseMessageContext("<empty/>");
synCtx.setProperty(REMOTE_ADDR, "192.168.8.212");
SynapseConfiguration synCfg = new SynapseConfiguration();
synCtx.setConfiguration(synCfg);
for (int i = 0; i < 6; i++) {
try {
throttleMediator.mediate(synCtx);
Thread.sleep(1000);
}
catch (Exception e) {
if (i == 3) {
assertTrue(e.getMessage().lastIndexOf("IP_BASE") > 0);
}
if (i == 4) {
assertTrue(e.getMessage().lastIndexOf("IP_BASE") > 0);
}
if (i == 5) {
assertTrue(e.getMessage().lastIndexOf("IP_BASE") > 0);
}
}
}
}
public class ThrottleTestMediator extends AbstractMediator {
private String policyKey = null;
Throttle throttle = null;
private OMElement inLinePolicy = null;
public boolean mediate(MessageContext synCtx) {
init(synCtx);
try {
return canAccess(synCtx);
}
catch (
ThrottleException e) {
throw new SynapseException(e.getMessage());
}
}
protected boolean canAccess(MessageContext synContext)
throws SynapseException, ThrottleException {
if (throttle == null) {
throw new ThrottleException("Can not find a throttle");
}
//IP based throttling
String remoteIP = (String) synContext.getProperty(REMOTE_ADDR);
if (remoteIP == null) {
throw new ThrottleException("IP address of the caller can not find - " +
"Currently only support caller-IP base access control" +
"- Throttling will not happen ");
} else {
ThrottleContext throttleContext
= throttle.getThrottleContext(ThrottleConstants.IP_BASED_THROTTLE_KEY);
if (throttleContext == null) {
throw new ThrottleException("Can not find a configuration for " +
"IP Based Throttle");
}
AccessRateController accessController;
try {
accessController = new AccessRateController();
boolean canAccess = accessController.canAccess(
throttleContext, remoteIP, ThrottleConstants.IP_BASE).isAccessAllowed();
if (!canAccess) {
throw new SynapseException("Access has currently been denied by" +
" the IP_BASE throttle for IP :\t" + remoteIP);
}
return canAccess;
}
catch (ThrottleException e) {
return true;
}
}
}
protected void init(MessageContext synContext) {
boolean reCreate = false; // It is not need to recreate ,if property is not dyanamic
OMElement policyOmElement = null;
if (policyKey != null) {
Entry entry = synContext.getConfiguration().getEntryDefinition(policyKey);
if (entry == null) {
return;
}
Object entryValue = entry.getValue();
if (!(entryValue instanceof OMElement)) {
return;
}
// if entry is dynamic, need to check wheather updated or not
if ((!entry.isCached() || entry.isExpired())) {
reCreate = true;
}
policyOmElement = (OMElement) entryValue;
} else if (inLinePolicy != null) {
policyOmElement = inLinePolicy;
}
if (policyOmElement == null) {
return;
}
if (!reCreate) {
//The first time creation
if (throttle == null) {
createThrottleMetaData(policyOmElement);
}
} else {
createThrottleMetaData(policyOmElement);
}
}
protected void createThrottleMetaData(OMElement policyOmElement) {
try {
throttle = ThrottleFactory.createMediatorThrottle(policyOmElement);
}
catch (ThrottleException e) {
throw new SynapseException(e.getMessage());
}
}
public String getType() {
return "ThrottleMediator";
}
public String getPolicyKey() {
return policyKey;
}
public void setPolicyKey(String policyKey) {
this.policyKey = policyKey;
}
public OMElement getInLinePolicy() {
return inLinePolicy;
}
public void setInLinePolicy(OMElement inLinePolicy) {
this.inLinePolicy = inLinePolicy;
}
}
}