Skip to content

Commit

Permalink
Merge pull request #1314 from chaudharydeepak/develop
Browse files Browse the repository at this point in the history
#1165 - filter expired cookies when injected in httpClient
  • Loading branch information
ptrthomas authored Oct 10, 2020
2 parents d74ecdb + 0992955 commit 038802f
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,11 @@
import com.intuit.karate.Config;
import com.intuit.karate.FileUtils;
import com.intuit.karate.core.ScenarioContext;
import org.apache.http.conn.ssl.LenientSslConnectionSocketFactory;

import static com.intuit.karate.http.Cookie.*;

import com.intuit.karate.http.HttpClient;
import com.intuit.karate.http.HttpRequest;
import com.intuit.karate.http.HttpResponse;
import com.intuit.karate.http.HttpUtils;
import com.intuit.karate.http.MultiPartItem;
import com.intuit.karate.http.MultiValuedMap;
import java.io.IOException;

import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import javax.net.ssl.SSLContext;

import com.intuit.karate.http.*;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.ParseException;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CookieStore;
Expand All @@ -67,22 +41,28 @@
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.*;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.Map.Entry;

import static com.intuit.karate.http.Cookie.*;

/**
* @author pthomas3
*/
Expand Down Expand Up @@ -269,6 +249,15 @@ protected void buildCookie(com.intuit.karate.http.Cookie c) {
case PATH:
cookie.setPath(entry.getValue());
break;
case EXPIRES: // add expires field for cookie.
try {
cookie.setExpiryDate(Date.from(ZonedDateTime.parse(entry.getValue(), DTFMTR_RFC1123).toInstant()));
}
catch ( DateTimeParseException ex)
{
System.err.println("ex ->" + ex.getLocalizedMessage());
}
break;
}
}
if (cookie.getDomain() == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.intuit.karate.http.apache;

import com.intuit.karate.CallContext;
import com.intuit.karate.Config;
import com.intuit.karate.core.FeatureContext;
import com.intuit.karate.core.ScenarioContext;
import com.intuit.karate.http.Cookie;
import org.apache.http.client.CookieStore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.time.ZonedDateTime;
import java.util.LinkedHashMap;
import java.util.Map;

import static com.intuit.karate.http.Cookie.*;
import static com.intuit.karate.http.HttpClient.construct;
import static org.junit.Assert.assertEquals;

public class ApacheHttpClientTest {

private static final Logger logger = LoggerFactory.getLogger(ApacheHttpClientTest.class);

private ScenarioContext getContext() {
FeatureContext featureContext = FeatureContext.forEnv();
CallContext callContext = new CallContext(null, true);
return new ScenarioContext(featureContext, callContext, null, null);
}

private Config getConfig() {
return new Config();
}

private Map<String, String> getCookieMapWithExpiredDate() {
ZonedDateTime currentDate = ZonedDateTime.now();
Map<String, String> cookieMap = new LinkedHashMap<>();
cookieMap.put(NAME, "testCookie");
cookieMap.put(VALUE, "tck");
cookieMap.put(DOMAIN, ".com");
cookieMap.put(PATH, "/");
cookieMap.put(EXPIRES,currentDate.minusDays(1).format(DTFMTR_RFC1123));
return cookieMap;
}

private Map<String, String> getCookieMapWithNonExpiredDate() {
ZonedDateTime currentDate = ZonedDateTime.now();
Map<String, String> cookieMap = new LinkedHashMap<>();
cookieMap.put(NAME, "testCookie");
cookieMap.put(VALUE, "tck");
cookieMap.put(DOMAIN, ".com");
cookieMap.put(PATH, "/");
cookieMap.put(EXPIRES, currentDate.plusDays(1).format(DTFMTR_RFC1123));
return cookieMap;
}

@Test
public void testExpiredCookieIsRemoved() throws NoSuchFieldException, IllegalAccessException {
com.intuit.karate.http.Cookie c = new Cookie(getCookieMapWithExpiredDate());
ApacheHttpClient httpClient = (ApacheHttpClient) construct(getConfig(), getContext());
httpClient.buildCookie(c);

Field cookieStoreField = httpClient.getClass().getDeclaredField("cookieStore");
cookieStoreField.setAccessible(true);
CookieStore fieldValue = (CookieStore) cookieStoreField.get(httpClient);
assertEquals(0, fieldValue.getCookies().size());
}

@Test
public void testNonExpiredCookieIsPersisted() throws NoSuchFieldException, IllegalAccessException {
com.intuit.karate.http.Cookie c = new Cookie(getCookieMapWithNonExpiredDate());
ApacheHttpClient httpClient = (ApacheHttpClient) construct(getConfig(), getContext());
httpClient.buildCookie(c);

Field cookieStoreField = httpClient.getClass().getDeclaredField("cookieStore");
cookieStoreField.setAccessible(true);
CookieStore fieldValue = (CookieStore) cookieStoreField.get(httpClient);
assertEquals(1, fieldValue.getCookies().size());
}
}


3 changes: 3 additions & 0 deletions karate-apache/src/test/resources/karate-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function fn() {
return { someConfig: 'someValue' }
}
2 changes: 2 additions & 0 deletions karate-apache/src/test/resources/karate-http.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
client.class=com.intuit.karate.http.apache.ApacheHttpClient

34 changes: 27 additions & 7 deletions karate-core/src/main/java/com/intuit/karate/http/Cookie.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
*/
package com.intuit.karate.http;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.util.*;

/**
*
Expand All @@ -44,7 +46,10 @@ public class Cookie extends LinkedHashMap<String, String> {
public static final String MAX_AGE = "max-age";
public static final String SECURE = "secure";
public static final String PERSISTENT = "persistent";
public static final String HTTP_ONLY = "http-only";
public static final String HTTP_ONLY = "http-only";
public static final DateTimeFormatter DT_FMT_V1 = DateTimeFormatter.ofPattern("EEE, dd-MMM-yy HH:mm:ss z");
public static final DateTimeFormatter DT_FMT_V2 = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z");
public static final DateTimeFormatter DTFMTR_RFC1123 = new DateTimeFormatterBuilder().appendOptional(DT_FMT_V1).appendOptional(DT_FMT_V2).toFormatter();

// cookies can be a map of maps, so some extra processing
public static List<Cookie> toCookies(Map<String, Object> map) {
Expand Down Expand Up @@ -82,6 +87,21 @@ public String getName() {

public String getValue() {
return get(VALUE);
}
}

public boolean isCookieExpired()
{
String exprDat = get(EXPIRES);
Date expires = null;
if ( null != exprDat) {
try {
expires = Date.from(ZonedDateTime.parse(get(EXPIRES), DTFMTR_RFC1123).toInstant());
} catch (DateTimeParseException ex) {
System.err.println("ex ->" + ex.getLocalizedMessage());
}
}
return null != expires && !expires.after(new Date());

}

}
64 changes: 57 additions & 7 deletions karate-demo/src/test/java/demo/cookies/cookies.feature
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,25 @@ Scenario: one cookie, and it is sent automatically in the next request
Then status 200
And match response == '#[1]'
And match response[0] contains { name: 'foo', value: 'bar' }

Given path 'search', 'cookies'
And request {}
When method post
Then status 200
And match response == '#[1]'
And match response[0] contains { name: 'foo', value: 'bar' }
And match response[0] contains { name: 'foo', value: 'bar' }

* print 'cookies: ', responseCookies

# reset cookies
* configure cookies = null
Given path 'search', 'cookies'
Given path 'search', 'cookies'
When method get
Then status 200
And match response == []

# modify cookies
Given path 'search', 'cookies'
Given path 'search', 'cookies'
And cookie foo = 'blah'
And request {}
When method post
Expand All @@ -43,15 +43,65 @@ Scenario: one cookie, and it is sent automatically in the next request

Scenario: cookie as json
Given path 'search', 'cookies'
And cookie foo = { value: 'bar' }
And cookie foo = { value: 'bar' }
When method get
Then status 200
And match response[0] contains { name: 'foo', value: 'bar' }

Scenario: cookie returned has dots in the domain which violates RFC 2109
Given path 'search', 'cookies'
And cookie foo = { value: 'bar' }
And cookie foo = { value: 'bar' }
And param domain = '.abc.com'
When method get
Then status 200
And match response[0] contains { name: 'foo', value: 'bar', domain: '.abc.com' }

Scenario: cookie returned has dots in the domain which violates RFC 2109
Given path 'search', 'cookies'
And cookie foo = { value: 'bar' }
And param domain = '.abc.com'
When method get
Then status 200
And match response[0] contains { name: 'foo', value: 'bar', domain: '.abc.com' }

@mock-servlet-todo
Scenario: expired cookie is not in response
* def prevDate =
"""
function() {
var SimpleDateFormat = Java.type('java.text.SimpleDateFormat');
var Calendar = Java.type('java.util.Calendar');
var currCalIns = Calendar.getInstance();
currCalIns.add(java.util.Calendar.DATE, -1);
var sdf = new SimpleDateFormat("EEE, dd-MMM-yy HH:mm:ss z");
return sdf.format(currCalIns.getTime());
}
"""
* def date = prevDate()
Given path 'search', 'cookies'
And cookie foo = {value:'bar', expires: '#(date)'}
And param domain = '.abcdfdf.com'
When method get
Then status 200
And match response == []

@mock-servlet-todo
Scenario: non-expired cookie is in response
* def futureDate =
"""
function() {
var SimpleDateFormat = Java.type('java.text.SimpleDateFormat');
var Calendar = Java.type('java.util.Calendar');
var currCalIns = Calendar.getInstance();
currCalIns.add(java.util.Calendar.DATE, +1);
var sdf = new SimpleDateFormat("EEE, dd-MMM-yy HH:mm:ss z");
return sdf.format(currCalIns.getTime());
}
"""
* def date = futureDate()
Given path 'search', 'cookies'
And cookie foo = {value:'bar', expires:'#(date)', path:'/search'}
And param domain = '.abc.com'
When method get
Then status 200
And match response[0] contains { name: 'foo', value: 'bar', domain: '.abc.com' }
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.List;
import java.util.Map.Entry;
import javax.net.ssl.HttpsURLConnection;
Expand All @@ -59,6 +63,7 @@
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
import org.glassfish.jersey.message.internal.StringBuilderUtils;

/**
*
Expand Down Expand Up @@ -144,8 +149,12 @@ public void buildHeader(String name, Object value, boolean replace) {

@Override
public void buildCookie(com.intuit.karate.http.Cookie c) {
Cookie cookie = new Cookie(c.getName(), c.getValue());
builder.cookie(cookie);
// only add the cookie from request, if it isnt already expired.
if ( !c.isCookieExpired() )
{
Cookie cookie = new Cookie(c.getName(), c.getValue());
builder.cookie(cookie);
}
}

private MediaType getMediaType(String mediaType) {
Expand Down

0 comments on commit 038802f

Please sign in to comment.