Mercurial > stress-tester
changeset 727:7bc4eb666b7f
ConverterHttpClient - filters
author | Devel 1 |
---|---|
date | Fri, 01 Dec 2017 14:25:20 +0100 |
parents | af5daf4a3879 |
children | c3a2898241a0 |
files | stress-tester/src/main/java/com/passus/st/ConverterHttpClient.java stress-tester/src/test/java/com/passus/st/ConverterHttpClientTest.java |
diffstat | 2 files changed, 354 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/stress-tester/src/main/java/com/passus/st/ConverterHttpClient.java Fri Dec 01 14:25:05 2017 +0100 +++ b/stress-tester/src/main/java/com/passus/st/ConverterHttpClient.java Fri Dec 01 14:25:20 2017 +0100 @@ -4,10 +4,17 @@ import com.passus.commons.service.Service; import com.passus.st.client.Event; import com.passus.st.client.EventHandler; +import com.passus.st.client.SessionStatusEvent; +import com.passus.st.client.http.HttpFlowContext; +import com.passus.st.client.http.HttpScopes; +import com.passus.st.client.http.HttpSessionPayloadEvent; import com.passus.st.client.http.filter.HttpFilter; import com.passus.st.client.http.filter.HttpFilterAware; import com.passus.st.client.http.filter.HttpFilterChain; +import com.passus.st.emitter.SessionInfo; import com.passus.st.source.EventDestination; +import java.util.HashMap; +import java.util.Map; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -21,6 +28,8 @@ private final EventDestination dst; private final HttpFilterChain filterChain = new HttpFilterChain(); + private final HttpScopes scopes = new HttpScopes(); + protected final Map<SessionInfo, HttpFlowContext> sessions = new HashMap<>(); private boolean started; @@ -66,6 +75,29 @@ } try { + switch (event.getType()) { + case SessionStatusEvent.TYPE: { + SessionStatusEvent e = (SessionStatusEvent) event; + // tworzyc HttpFlowContext ??? + if (e.getStatus() == SessionStatusEvent.STATUS_CLOSED) { + deregisterFlow(e.getSessionInfo()); + } + } + case HttpSessionPayloadEvent.TYPE: { + HttpSessionPayloadEvent e = (HttpSessionPayloadEvent) event; + HttpFlowContext flow = getFlow(e.getSessionInfo()); + int result = filterChain.filterOutbound(e.getRequest(), e.getResponse(), flow); + if (result == HttpFilter.ACCEPT) { + // krok potrzebny dla kilku filtrów, np session, digestLogin + flow.setSentEvent(e); + filterChain.filterInbound(e.getRequest(), e.getResponse(), flow); + } else { + return; // skip dst.handle() + } + break; + } + } + dst.handle(event); } catch (Exception e) { LOGGER.debug(e.getMessage(), e); @@ -81,4 +113,21 @@ public void join() { } + HttpScopes scopes() { + return scopes; + } + + private HttpFlowContext getFlow(SessionInfo session) { + HttpFlowContext flowContext = sessions.get(session); + if (flowContext == null) { + flowContext = new HttpFlowContext(session, scopes); + sessions.put(session, flowContext); + } + return flowContext; + + } + + private HttpFlowContext deregisterFlow(SessionInfo session) { + return sessions.remove(session); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester/src/test/java/com/passus/st/ConverterHttpClientTest.java Fri Dec 01 14:25:20 2017 +0100 @@ -0,0 +1,305 @@ +package com.passus.st; + +import static com.passus.commons.collection.FluentBuilder.e; +import static com.passus.commons.collection.FluentBuilder.map; +import com.passus.net.http.HttpHeaders; +import com.passus.net.http.HttpMessageHelper; +import com.passus.net.http.HttpMethod; +import com.passus.net.http.HttpParameters; +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.net.http.HttpStatus; +import com.passus.st.client.Event; +import com.passus.st.client.credentials.Credentials; +import com.passus.st.client.credentials.CredentialsProvider; +import static com.passus.st.client.http.HttpConsts.PARAM_USERNAME; +import static com.passus.st.client.http.HttpConsts.TAG_MARKER; +import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID; +import static com.passus.st.client.http.HttpConsts.TAG_ZONE; +import com.passus.st.client.http.HttpSessionPayloadEvent; +import com.passus.st.client.http.filter.*; +import com.passus.st.client.http.filter.HttpMessageModificationFilter.PostDataSetParamOperation; +import com.passus.st.client.http.filter.HttpMessageModificationFilter.SetCookieOperation; +import com.passus.st.client.http.filter.HttpMessageModificationFilter.SetHeaderOperation; +import com.passus.st.client.http.filter.HttpMessageModificationFilter.SetQueryParameterOperation; +import com.passus.st.emitter.SessionInfo; +import com.passus.st.source.ArrayListEventDestination; +import com.passus.st.source.NullEventDestination; +import com.passus.st.utils.TestHttpUtils; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.apache.logging.log4j.Level; +import static org.testng.AssertJUnit.*; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author mikolaj.podbielski + */ +public class ConverterHttpClientTest { + + static SessionInfo SI = new SessionInfo("1.1.1.1", 11000, "1.1.1.2", 80); + static Credentials CREDENTIALS = new Credentials("test", "test"); + static CredentialsProvider PROVIDER = HttpAbstractLoginFilterTest.provider(CREDENTIALS); + static NullEventDestination DST = new NullEventDestination(); + + static { + Log4jConfigurationFactory.enableFactory(Level.DEBUG); + } + + @BeforeClass + public static void beforeClass() { + AppUtils.registerAll(); + } + + @AfterClass + public static void afterClass() { + AppUtils.unregisterAll(); + } + + static HttpSessionPayloadEvent ev(HttpRequest req, HttpResponse resp) { + return new HttpSessionPayloadEvent(SI, req, resp, "test"); + } + + static ConverterHttpClient client(HttpFilter... filters) { + ConverterHttpClient client = new ConverterHttpClient(DST); + for (HttpFilter filter : filters) { + client.addFilter(filter); + } + client.start(); + return client; + } + + @Test + public void testBasicLogin_filterShouldReplaceCredentials() { + final String REQS = "GET /basic/index.html HTTP/1.1\r\n" + + "Authorization: Basic dXNlcjpwYXNzd29yZA==\r\n\r\n"; + HttpRequest req = TestHttpUtils.request(REQS); + HttpResponse resp = HttpResponseBuilder.ok().build(); + + HttpBasicAuthLoginFilter f = HttpBasicAuthLoginFilterTest.createFilter(PROVIDER); + ConverterHttpClient client = client(f); + client.handle(ev(req, resp)); + + assertEquals(req.getHeaders().get(HttpHeaders.AUTHORIZATION).toString(), "Basic dGVzdDp0ZXN0"); + assertEquals(client.scopes().getConversation(req).get(PARAM_USERNAME), "test"); + } + + @Test + public void testDigestLogin_filterShouldReplaceCredentials() { + final String RESP1S = "HTTP/1.1 401 Unauthorized\r\n" + + "Date: Fri, 09 Jun 2017 06:25:27 GMT\r\n" + + "WWW-Authenticate: Digest realm=\"realm\", nonce=\"old-nonce\", algorithm=MD5, qop=\"auth\"\r\n" + + "Content-Length: 12\r\n\r\nUnauthorized"; + final String REQ2S = "GET /html/digest/index2.html HTTP/1.1\r\n" + + "Host: 172.16.60.101\r\n" + + "Authorization: Digest username=\"user\", realm=\"realm\", nonce=\"old-nonce\"," + + " uri=\"/html/digest/index2.html\", algorithm=MD5, response=\"774280b22c9ed40bc500bba5c431d8c7\"," + + " qop=auth, nc=00000001, cnonce=\"cnonce\"\r\n\r\n"; + final String RESP2S = "HTTP/1.1 200 OK\n" + + "Authentication-Info: rspauth=\"?\", cnonce=\"?\", nc=00000001, qop=auth\r\n" + + "Content-Length: 33\r\n\r\n<html><body>content</body></html>"; + + HttpRequest req1 = HttpRequestBuilder.get("http://html/digest/index2.html").build(); + HttpResponse resp1 = TestHttpUtils.response(RESP1S); + HttpRequest req2 = TestHttpUtils.request(REQ2S); + HttpResponse resp2 = TestHttpUtils.response(RESP2S); + req2.setTag(TAG_SESSION_ID, "sid1"); + + HttpDigestAuthLoginFilter f = HttpDigestAuthLoginFilterTest.createFilter(CREDENTIALS); + ConverterHttpClient client = client(f); + client.handle(ev(req1, resp1)); + client.handle(ev(req2, resp2)); + + assertEquals(client.scopes().getConversation(req2).get(PARAM_USERNAME), "test"); + assertEquals(client.scopes().getSession(req2).get(PARAM_USERNAME), "test"); + } + + @Test + public void testFormLogin() throws IOException { + final String REQS = "POST /login_check HTTP/1.1\r\n" + + "Host: 172.16.60.23\r\n" + + "Content-Type: application/x-www-form-urlencoded\r\n" + + "Content-Length: 32\r\n" + + "Cookie: PHPSESSID=4r7tg8275ih7p0uh79im6q5643\r\n\r\n" + + "_username=admin&_password=qwerty"; + final String RESPS = "HTTP/1.1 302 Found\r\n" + + "Set-Cookie: PHPSESSID=pcap_post; path=/; HttpOnly\r\n" + + "Location: http://172.16.60.23/\r\n" + + "Content-Length: 2\r\n\r\n" + + "OK"; + + HttpRequest req = TestHttpUtils.request(REQS); + HttpResponse resp = TestHttpUtils.response(RESPS); + req.setTag(TAG_SESSION_ID, "sid1"); + + HttpFormLoginFilter f = HttpFormLoginFilterTest.createFilter(PROVIDER); + ConverterHttpClient client = client(f); + client.handle(ev(req, resp)); + + HttpFormLoginFilterTest.assertContent(req, "_username=test&_password=test"); + assertEquals(client.scopes().getConversation(req).get(PARAM_USERNAME), "test"); + assertEquals(client.scopes().getSession(req).get(PARAM_USERNAME), "test"); + } + + @Test + public void testMatcher() { + HttpRequest req1 = HttpRequestBuilder.get("http://test.com/test").build(); + HttpRequest req2 = HttpRequestBuilder.get("http://test2.com/test2").build(); + HttpResponse resp1 = HttpResponseBuilder.ok().build(); + HttpResponse resp2 = HttpResponseBuilder.status(HttpStatus.NO_CONTENT).build(); + + ArrayListEventDestination dst = new ArrayListEventDestination(); + HttpMessagePredicate predicate = HttpFilterTestUtils.createPredicate("{req.url: {$contains: test2}}"); + HttpMatchFilter f = new HttpMatchFilter(); + f.setPredicate(predicate); + f.setAcceptOnMatch(false); + + ConverterHttpClient client = new ConverterHttpClient(dst); + client.addFilter(f); + client.start(); + + client.handle(ev(req1, resp1)); // match:false filter:dunno chain:accept + client.handle(ev(req2, resp2)); // match:true filter:deny chain:deny + + assertEquals(1, dst.getEvents().size()); + HttpSessionPayloadEvent event = dst.findFirst(HttpSessionPayloadEvent.class); + assertEquals(200, event.getResponse().getStatus().getCode()); + } + + @Test + public void testModifyMessage() throws IOException { + HttpRequest req = HttpRequestBuilder + .post("http://test.com/path/test?uParam1=1", "param1=value1¶m2=value2") + .header("Header1", "Header1Value1") + .header("Cookie", "myCookie1=myValue1;myCookie2=myValue2") + .build(); + + HttpMessageModificationFilter f = new HttpMessageModificationFilter(); + f.addOperation(new SetHeaderOperation("Header1", "Header1Value1a")); + f.addOperation(new SetCookieOperation("myCookie1", "myValue1a")); + f.addOperation(new PostDataSetParamOperation("param1", "value1a")); + f.addOperation(new SetQueryParameterOperation("uParam1", "11")); + ConverterHttpClient client = client(f); + + client.handle(ev(req, null)); + HttpHeaders headers = req.getHeaders(); + HttpParameters params = HttpMessageHelper.get().decodeFormUrlencoded(req); + + assertEquals("/path/test?uParam1=11", req.getUri().toString()); + assertEquals("Header1Value1a", headers.get("Header1").toString()); + assertEquals("myCookie1=myValue1a;myCookie2=myValue2", headers.get("Cookie").toString()); + assertEquals("param2=value2¶m1=value1a", params.toString()); + } + + @Test + public void testDateRewriter_() { + HttpRequest req = HttpRequestBuilder.get("http://example.com/") + .header(HttpHeaders.DATE, "Wed, 09-Sep-2009 09:09:00 GMT") + .build(); + + HttpDateFilter f = new HttpDateFilter(); + HttpDateFilterTest.setDate(f, 1500_000_000_000L); + ConverterHttpClient client = client(f); + + client.handle(ev(req, null)); + assertEquals(req.getHeaders().get(HttpHeaders.DATE).toString(), "Fri, 14 Jul 2017 02:40:00 GMT"); + } + + @Test + public void testHostRewriter() { + HttpRequest req = HttpRequestBuilder.get("http://example.com:8080/site1/resource1") + .header(HttpHeaders.ORIGIN, "http://example.com:8080/site1") + .header(HttpHeaders.REFERER, "http://example.com:8080/site1/index") + .build(); + + HttpHostRewriterFilter f = new HttpHostRewriterFilter(); + f.setHostMap(map(e("example.com:8080", "example.org"))); + ConverterHttpClient client = client(f); + + client.handle(ev(req, null)); + + HttpHeaders headers = req.getHeaders(); + assertEquals(headers.get(HttpHeaders.HOST).toString(), "example.org"); + assertEquals(headers.get(HttpHeaders.ORIGIN).toString(), "http://example.org/site1"); + assertEquals(headers.get(HttpHeaders.REFERER).toString(), "http://example.org/site1/index"); + } + + @Test + public void testHeaderCleaners() { + HttpRequest req = HttpRequestBuilder.get("http://www.example.com/abc") + .header(HttpHeaders.ACCEPT, "*/*;q=0.5") + .header(HttpHeaders.IF_MODIFIED_SINCE, "09 Sep 2009 09:09:00 GMT") + .header(HttpHeaders.X_FORWARDED_FOR, "15.16.73.33") + .build(); + HttpResponse resp = HttpResponseBuilder.ok().build(); + + HttpFilter f1 = new HttpRequestCacheHeadersCleanerFilter(); + HttpFilter f2 = new HttpRequestProxyHeadersCleanerFilter(); + ConverterHttpClient client = client(f1, f2); + + client.handle(ev(req, resp)); + HttpHeaders headers = req.getHeaders(); + + assertTrue(headers.contains(HttpHeaders.ACCEPT)); + assertFalse(headers.contains(HttpHeaders.IF_MODIFIED_SINCE)); + assertFalse(headers.contains(HttpHeaders.X_FORWARDED_FOR)); + } + + @Test + public void testZone_() { + HttpRequest req = HttpRequestBuilder.get("http://test.com/test").build(); + HttpResponse resp = HttpResponseBuilder.ok().build(); + HttpMessagePredicate predicate = HttpFilterTestUtils.createPredicate("{req.url: {$contains: test}}"); + + HttpZoneFilter f = new HttpZoneFilter(); + f.addRule(new HttpZoneFilter.Rule("testZone", predicate)); + ConverterHttpClient client = client(f); + + client.handle(ev(req, resp)); + + assertEquals("testZone", req.getTag(TAG_ZONE)); + assertEquals("testZone", resp.getTag(TAG_ZONE)); + } + + @Test + public void testMVEL() { + HttpRequest req = HttpRequestBuilder.get("http://example.com/index.html").build(); + + String expression = "$req.setMethod(com.passus.net.http.HttpMethod.HEAD);" + + "$req.getUri().toString().equals(\"/index.html\") ? 1 : 0"; + + HttpMvelFilter f = new HttpMvelFilter(); + f.setStatement(HttpMvelFilterTest.es(expression)); + f.setDirection(HttpFilterDirection.OUT); + ConverterHttpClient client = client(f); + + client.handle(ev(req, null)); + + assertEquals(HttpMethod.HEAD, req.getMethod()); + } + + @Test + public void testMarker_() { + HttpRequest req = HttpRequestBuilder.get("http://test/test").build(); + + HttpMessagePredicate predicate = HttpFilterTestUtils.createPredicate("{req.url: {$contains: test}}"); + HttpMarkFilter f = new HttpMarkFilter(); + f.addRule(new HttpMarkFilter.MarkerRule("category1", predicate)); + ConverterHttpClient client = client(f); + + client.handle(ev(req, null)); + + List<HttpMarkFilter.Marker> markers = (List<HttpMarkFilter.Marker>) req.getTag(TAG_MARKER); + assertFalse(markers == null); + assertFalse(markers.isEmpty()); + HttpMarkFilter.Marker marker = markers.get(0); + + assertEquals("category1", marker.getCategory()); + } +}