changeset 525:924eac805b34

HttpZoneFilter
author Devel 2
date Tue, 29 Aug 2017 12:45:02 +0200
parents 73fa34b62fa1
children c72b7f546870
files stress-tester/src/main/java/com/passus/st/client/http/filter/HttpZoneFilter.java stress-tester/src/test/java/com/passus/st/client/http/filter/HttpZoneFilterTest.java
diffstat 2 files changed, 287 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpZoneFilter.java	Tue Aug 29 12:45:02 2017 +0200
@@ -0,0 +1,198 @@
+package com.passus.st.client.http.filter;
+
+import com.passus.commons.Assert;
+import com.passus.commons.annotations.Plugin;
+import com.passus.commons.utils.ArrayUtils;
+import com.passus.config.CListNode;
+import com.passus.config.CMapNode;
+import com.passus.config.CNode;
+import com.passus.config.CTupleNode;
+import com.passus.config.CValueNode;
+import com.passus.config.Configuration;
+import com.passus.config.NodeConversionException;
+import com.passus.config.annotations.NodeDefinitionCreate;
+import static com.passus.config.schema.ConfigurationSchemaBuilder.mapDef;
+import static com.passus.config.schema.ConfigurationSchemaBuilder.tupleDef;
+import com.passus.config.schema.NodeDefinition;
+import com.passus.config.schema.NodeDefinitionCreator;
+import com.passus.config.validation.Errors;
+import static com.passus.config.validation.ValidationDefaultMessages.GENERAL_CONVERSION_ERROR;
+import com.passus.filter.config.PredicateNodeTransformer;
+import com.passus.net.http.HttpRequest;
+import com.passus.net.http.HttpResponse;
+import static com.passus.st.client.http.HttpConsts.TAG_ZONE;
+import com.passus.st.client.http.HttpFlowContext;
+import com.passus.st.plugin.PluginConstants;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
+/**
+ *
+ * @author Mirosław Hawrot
+ */
+@NodeDefinitionCreate(HttpZoneFilter.HttpZoneFilterNodeDefCreator.class)
+@Plugin(name = HttpZoneFilter.TYPE, category = PluginConstants.CATEGORY_HTTP_FILTER)
+public class HttpZoneFilter extends HttpFilter {
+
+    public static final String TYPE = "zone";
+
+    public static class Rule {
+
+        private final String zone;
+
+        private final HttpMessagePredicate predicate;
+
+        public Rule(String zone, HttpMessagePredicate predicate) {
+            Assert.notNull(zone, "zone");
+            Assert.notNull(predicate, "predicate");
+            this.zone = zone;
+            this.predicate = predicate;
+        }
+
+        public String getZone() {
+            return zone;
+        }
+
+        public boolean match(HttpRequest req, HttpResponse resp, HttpFlowContext context) {
+            return predicate.test(new HttpMessageWrapper(req, resp, context));
+        }
+
+    }
+
+    private final List<Rule> rules = new ArrayList<>();
+
+    public HttpZoneFilter() {
+    }
+
+    public HttpZoneFilter(List<Rule> rules) {
+        Assert.notContainsNull(rules, "rules");
+        this.rules.addAll(rules);
+    }
+
+    public void addRule(Rule rule) {
+        Assert.notNull(rule, "rule");
+        rules.add(rule);
+    }
+
+    public List<Rule> getRules() {
+        return Collections.unmodifiableList(rules);
+    }
+
+    @Override
+    public void configure(Configuration config) {
+        List<Rule> cfgRules = (List<Rule>) config.get("zones", Collections.EMPTY_LIST);
+        rules.clear();
+        rules.addAll(cfgRules);
+    }
+
+    @Override
+    public int filterOutbound(HttpRequest req, HttpResponse resp, HttpFlowContext context) {
+        if (req != null && !rules.isEmpty()) {
+            for (Rule rule : rules) {
+                if (rule.match(req, resp, context)) {
+                    req.setTag(TAG_ZONE, rule.zone);
+                    if (resp != null) {
+                        resp.setTag(TAG_ZONE, rule.zone);
+                    }
+                    break;
+                }
+            }
+        }
+
+        return DUNNO;
+    }
+
+    @Override
+    public int filterInbound(HttpRequest req, HttpResponse resp, HttpFlowContext context) {
+        if (req != null && resp != null) {
+            String zone = (String) req.getTag(TAG_ZONE);
+            if (zone != null) {
+                resp.setTag(TAG_ZONE, zone);
+            }
+        }
+
+        return DUNNO;
+    }
+
+    @Override
+    public HttpFilter instanceForWorker(int index) {
+        return new HttpZoneFilter(rules);
+    }
+
+    public static class HttpZoneFilterNodeDefCreator implements NodeDefinitionCreator {
+
+        @Override
+        public NodeDefinition create() {
+            return mapDef(
+                    tupleDef("zones", new HttpZoneFilterRuleNodeDefinition())
+            );
+        }
+
+    }
+
+    public static class HttpZoneFilterRuleNodeDefinition extends NodeDefinition<HttpZoneFilterRuleNodeDefinition> {
+
+        private final static Set<Class<? extends CNode>> SUPPORTED = ArrayUtils.asUnmodifiableSet(CMapNode.class);
+
+        private static final PredicateNodeTransformer TRANSFORMER = new PredicateNodeTransformer();
+
+        @Override
+        public Set<Class<? extends CNode>> getSupportedNode() {
+            return SUPPORTED;
+        }
+
+        @Override
+        protected void doValidate(CNode node, Errors errors) {
+            CMapNode mapNode = (CMapNode) node;
+            for (CTupleNode tuple : mapNode.getChildren()) {
+                try {
+                    errors.pushNestedPath(tuple.getName());
+
+                } finally {
+                    errors.popNestedPath();
+                }
+            }
+        }
+
+        @Override
+        protected CNode doTransform(CNode node, Errors errors, boolean reverse) {
+            if (!reverse) {
+                CMapNode mapNode = (CMapNode) node;
+                CListNode listNode = new CListNode();
+
+                for (CTupleNode tuple : mapNode.getChildren()) {
+                    try {
+                        errors.pushNestedPath(tuple.getName());
+
+                        try {
+                            Predicate predicate = TRANSFORMER.transform(tuple.getNode());
+                            HttpMessagePredicate msgPredicate = new HttpMessagePredicate(predicate);
+                            CValueNode valNode = new CValueNode(new Rule(tuple.getName(), msgPredicate));
+                            listNode.add(valNode);
+                        } catch (NodeConversionException ex) {
+                            errors.reject(node, ex.getMessage());
+                        } catch (Exception e) {
+                            errors.reject(tuple.getNode(), GENERAL_CONVERSION_ERROR);
+                        }
+
+                    } catch (Exception e) {
+                        errors.popNestedPath();
+                    }
+                }
+
+                return listNode;
+            } else {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        }
+
+        @Override
+        protected boolean doEquals(CNode node1, CNode node2) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpZoneFilterTest.java	Tue Aug 29 12:45:02 2017 +0200
@@ -0,0 +1,89 @@
+package com.passus.st.client.http.filter;
+
+import com.passus.config.validation.Errors;
+import com.passus.filter.config.PredicateNodeTransformer;
+import com.passus.net.http.HttpRequest;
+import com.passus.net.http.HttpRequestBuilder;
+import com.passus.net.http.HttpResponse;
+import com.passus.net.http.HttpResponseBuilder;
+import com.passus.st.AppUtils;
+import static com.passus.st.client.http.HttpConsts.TAG_ZONE;
+import com.passus.st.client.http.HttpFlowContext;
+import com.passus.st.client.http.filter.HttpZoneFilter.Rule;
+import java.util.List;
+import java.util.function.Predicate;
+import static org.testng.Assert.*;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Mirosław Hawrot
+ */
+public class HttpZoneFilterTest {
+
+    private final PredicateNodeTransformer nodeTransformer = new PredicateNodeTransformer();
+
+    @BeforeClass
+    public static void beforeClass() {
+        AppUtils.registerAll();
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        AppUtils.unregisterAll();
+    }
+
+    private HttpMessagePredicate predicate(String config) {
+        try {
+            Predicate predicate = nodeTransformer.transform(config);
+            return new HttpMessagePredicate(predicate);
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Test
+    public void testFilter() {
+        HttpRequest req = HttpRequestBuilder.get("http://test.com/test").build();
+        HttpResponse respOut = HttpResponseBuilder.ok().build();
+        HttpResponse respIn = HttpResponseBuilder.ok().build();
+
+        HttpZoneFilter filter = new HttpZoneFilter();
+        filter.addRule(new Rule("testZone", predicate("{req.url: {$contains: \"test\"}}")));
+
+        filter.filterOutbound(req, respOut, null);
+        filter.filterInbound(req, respIn, null);
+
+        assertEquals("testZone", req.getTag(TAG_ZONE));
+        assertEquals("testZone", respOut.getTag(TAG_ZONE));
+        assertEquals("testZone", respIn.getTag(TAG_ZONE));
+    }
+
+    @Test
+    public void testConfigure() throws Exception {
+        String filterConfig = "filters:\n"
+                + "    - type: zone\n"
+                + "      zones:\n"
+                + "        \"zone1\": {req.url: {$contains: \"test\"}}\n";
+
+        Errors errors = new Errors();
+        List<HttpFilter> filters = HttpFiltersConfigurator.getFilters(filterConfig, errors);
+
+        assertEquals(0, errors.getErrorCount());
+        assertEquals(1, filters.size());
+        assertTrue(filters.get(0) instanceof HttpZoneFilter);
+
+        HttpZoneFilter zoneFilter = (HttpZoneFilter) filters.get(0);
+        List<Rule> rules = zoneFilter.getRules();
+        assertEquals(1, rules.size());
+
+        Rule rule = rules.get(0);
+        assertEquals("zone1", rule.getZone());
+    }
+}