Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support url fitlers and header filters #1

Merged
merged 19 commits into from
Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
buildscript {
repositories {
jcenter()
google()
maven { url 'https://jitpack.io' }

}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'com.android.tools.build:gradle:3.2.1'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand All @@ -21,6 +24,8 @@ allprojects {
maven {
url "https://maven.google.com"
}
maven { url 'https://jitpack.io' }
google()
}
}

Expand All @@ -30,10 +35,10 @@ task clean(type: Delete) {

ext {
minSdkVersion = 16
targetSdkVersion = 26
compileSdkVersion = 26
buildToolsVersion = '26.0.1'
targetSdkVersion = 28
compileSdkVersion = 28
buildToolsVersion = '28.0.3'

supportLibVersion = '25.3.1'
okhttp3Version = '3.6.0'
supportLibVersion = '28.0.0'
okhttp3Version = '3.11.0'
}
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
2 changes: 1 addition & 1 deletion library-no-op/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ android {
}

dependencies {
compile "com.squareup.okhttp3:okhttp:$okhttp3Version"
implementation "com.squareup.okhttp3:okhttp:$okhttp3Version"
}

apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.content.Context;

import java.io.IOException;
import java.util.List;

import okhttp3.Interceptor;
import okhttp3.Request;
Expand All @@ -28,6 +29,18 @@
*/
public final class ChuckInterceptor implements Interceptor {

public ChuckInterceptor setFilterBody(boolean filterBoby) {
return this;
}

public ChuckInterceptor setFilterHeaderList(List<String> keyWordHeaderList) {
return this;
}

public ChuckInterceptor setFilterUrlList(List<String> keyWordUrlList) {
return this;
}

public enum Period {
ONE_HOUR,
ONE_DAY,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2017 Jeff Gilfelt.
*
* Licensed 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 com.readystatesoftware.chuck.internal.data;

import android.content.Context;


public class ChuckContentProvider {

public static String export(Context context) {
return null;
}
}
8 changes: 4 additions & 4 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ android {
}

dependencies {
compile 'com.google.code.gson:gson:2.8.0'
compile "com.squareup.okhttp3:okhttp:$okhttp3Version"
compile 'nl.qbusict:cupboard:2.2.0'
compile "com.android.support:design:$supportLibVersion"
implementation 'com.google.code.gson:gson:2.8.4'
implementation "com.squareup.okhttp3:okhttp:$okhttp3Version"
implementation 'nl.qbusict:cupboard:2.2.0'
implementation "com.android.support:design:$supportLibVersion"
}

apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
3 changes: 2 additions & 1 deletion library/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
-keep class com.readystatesoftware.chuck.internal.data.HttpTransaction { *; }
-keep class android.support.v7.widget.SearchView { *; }
-keep class android.support.v7.widget.SearchView { *; }
-dontnote com.readystatesoftware.chuck.internal.data.HttpTransaction
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import okhttp3.Headers;
import okhttp3.Interceptor;
Expand Down Expand Up @@ -78,6 +81,10 @@ public enum Period {
private final NotificationHelper notificationHelper;
private RetentionManager retentionManager;
private boolean showNotification;
private List<String> filterUrlList;
private List<String> filterHeaderList;
private boolean filterBody;

private long maxContentLength = 250000L;

/**
Expand All @@ -101,6 +108,36 @@ public ChuckInterceptor showNotification(boolean show) {
return this;
}

/**
* set all the http response body should be filtered.
* @param filterBody true if you want to filter all http response body.
*/
public ChuckInterceptor setFilterBody(boolean filterBody) {
this.filterBody = filterBody;
return this;
}

/**
* set the url key word list to stop chuck from caching its data.
* @param keyWordUrlList the url level key word list that is to stop chuck from caching its data. All of these data including
* request headers, request params, request url params, response header, response body will not be cached.
* @return The {@link ChuckInterceptor} instance.
*/
public ChuckInterceptor setFilterUrlList(List<String> keyWordUrlList) {
this.filterUrlList = keyWordUrlList;
return this;
}

/**
* set the header key word list to stop chuck from caching its data.
* @param keyWordHeaderList the header level key word list that is to stop chuck from caching the value of such header.
* @return The {@link ChuckInterceptor} instance.
*/
public ChuckInterceptor setFilterHeaderList(List<String> keyWordHeaderList) {
this.filterHeaderList = keyWordHeaderList;
return this;
}

/**
* Set the maximum length for request and response content before it is truncated.
* Warning: setting this value too high may cause unexpected results.
Expand All @@ -112,7 +149,7 @@ public ChuckInterceptor maxContentLength(long max) {
this.maxContentLength = max;
return this;
}

/**
* Set the retention period for HTTP transaction data captured by this interceptor.
* The default is one week.
Expand All @@ -125,6 +162,25 @@ public ChuckInterceptor retainDataFor(Period period) {
return this;
}

private String replacedUrl(String url) {
if (this.filterUrlList ==null){
return null;
}
for (String keyWord : filterUrlList) {
if (matches(url, keyWord)){
int endIndex = url.lastIndexOf("?");
return endIndex > 0 ? url.substring(0, endIndex) : url;
}
}
return null;
}

private boolean matches(String url, String regex) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(url);
return m.find();
}

@Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();

Expand All @@ -135,9 +191,18 @@ public ChuckInterceptor retainDataFor(Period period) {
transaction.setRequestDate(new Date());

transaction.setMethod(request.method());
transaction.setUrl(request.url().toString());

transaction.setRequestHeaders(request.headers());
String url = request.url().toString();
String replacedUrl = replacedUrl(url);
boolean urlNeedToBeFiltered = replacedUrl!=null;
if (!urlNeedToBeFiltered){
transaction.setUrl(url);
}else {
transaction.setUrl(replacedUrl);
}
if (!urlNeedToBeFiltered){
transaction.setRequestHeaders(request.headers(), filterHeaderList);
}
if (hasRequestBody) {
if (requestBody.contentType() != null) {
transaction.setRequestContentType(requestBody.contentType().toString());
Expand All @@ -158,7 +223,9 @@ public ChuckInterceptor retainDataFor(Period period) {
charset = contentType.charset(UTF8);
}
if (isPlaintext(buffer)) {
transaction.setRequestBody(readFromBuffer(buffer, charset));
if (!urlNeedToBeFiltered){
transaction.setRequestBody(readFromBuffer(buffer, charset));
}
} else {
transaction.setResponseBodyIsPlainText(false);
}
Expand All @@ -179,19 +246,21 @@ public ChuckInterceptor retainDataFor(Period period) {

ResponseBody responseBody = response.body();

transaction.setRequestHeaders(response.request().headers()); // includes headers added later in the chain
if (!urlNeedToBeFiltered) {
transaction.setRequestHeaders(response.request().headers(), filterHeaderList); // includes headers added later in the chain
}
transaction.setResponseDate(new Date());
transaction.setTookMs(tookMs);
transaction.setProtocol(response.protocol().toString());
transaction.setResponseCode(response.code());
transaction.setResponseMessage(response.message());

transaction.setResponseContentLength(responseBody.contentLength());
if (responseBody.contentType() != null) {
transaction.setResponseContentType(responseBody.contentType().toString());
}
transaction.setResponseHeaders(response.headers());

if (!urlNeedToBeFiltered) {
transaction.setResponseHeaders(response.headers(), filterHeaderList);
}
transaction.setResponseBodyIsPlainText(!bodyHasUnsupportedEncoding(response.headers()));
if (HttpHeaders.hasBody(response) && transaction.responseBodyIsPlainText()) {
BufferedSource source = getNativeSource(response);
Expand All @@ -208,7 +277,13 @@ public ChuckInterceptor retainDataFor(Period period) {
}
}
if (isPlaintext(buffer)) {
transaction.setResponseBody(readFromBuffer(buffer.clone(), charset));
if (!urlNeedToBeFiltered) {
if (!filterBody){
transaction.setResponseBody(readFromBuffer(buffer.clone(), charset));
}else {
transaction.setResponseBody("****** body has been hidden ******");
}
}
} else {
transaction.setResponseBodyIsPlainText(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;

import com.readystatesoftware.chuck.internal.support.JsonConvertor;

import java.util.ArrayList;
import java.util.List;

import nl.qbusict.cupboard.QueryResultIterable;

public class ChuckContentProvider extends ContentProvider {

Expand All @@ -37,6 +45,26 @@ public class ChuckContentProvider extends ContentProvider {

private ChuckDbOpenHelper databaseHelper;


@WorkerThread
public static String export(Context context){
ChuckDbOpenHelper chuckDbOpenHelper = new ChuckDbOpenHelper(context);
SQLiteDatabase readableDatabase = chuckDbOpenHelper.getReadableDatabase();
QueryResultIterable<HttpTransaction> iterable = LocalCupboard.getInstance().withDatabase(readableDatabase).query(HttpTransaction.class).query();
List<HttpTransaction> list = getListFromQueryResultIterator(iterable);
return JsonConvertor.getInstance().toJson(list);
}

private static List<HttpTransaction> getListFromQueryResultIterator(QueryResultIterable<HttpTransaction> iter) {

final List<HttpTransaction> transactionArrayList = new ArrayList<>();
for (HttpTransaction bunny : iter) {
transactionArrayList.add(bunny);
}
iter.close();
return transactionArrayList;
}

@Override
public void attachInfo(Context context, ProviderInfo info) {
super.attachInfo(context, info);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ public String getScheme() {
return scheme;
}

public void setRequestHeaders(Headers headers) {
setRequestHeaders(toHttpHeaderList(headers));
public void setRequestHeaders(Headers headers, List<String> filterHeaderList) {
setRequestHeaders(toHttpHeaderList(headers, filterHeaderList));
}

public void setRequestHeaders(List<HttpHeader> headers) {
Expand All @@ -267,8 +267,8 @@ public String getRequestHeadersString(boolean withMarkup) {
return FormatUtils.formatHeaders(getRequestHeaders(), withMarkup);
}

public void setResponseHeaders(Headers headers) {
setResponseHeaders(toHttpHeaderList(headers));
public void setResponseHeaders(Headers headers, List<String> filterHeaderList) {
setResponseHeaders(toHttpHeaderList(headers, filterHeaderList));
}

public void setResponseHeaders(List<HttpHeader> headers) {
Expand Down Expand Up @@ -349,14 +349,29 @@ public boolean isSsl() {
return scheme.toLowerCase().equals("https");
}

private List<HttpHeader> toHttpHeaderList(Headers headers) {
private List<HttpHeader> toHttpHeaderList(Headers headers, List<String> filterHeaderList) {
List<HttpHeader> httpHeaders = new ArrayList<>();
for (int i = 0, count = headers.size(); i < count; i++) {
httpHeaders.add(new HttpHeader(headers.name(i), headers.value(i)));
httpHeaders.add(new HttpHeader(headers.name(i), headerFiltered(filterHeaderList, headers.name(i)) ? "*****" : headers.value(i)));
}
return httpHeaders;
}

private boolean headerFiltered(List<String> filterHeaderList, String name) {
return filterHeaderList!=null && containsCaseInsensitive(filterHeaderList, name);
}

public boolean containsCaseInsensitive(List<String> stringList, String name){
for (String string : stringList){
if (string.equalsIgnoreCase(name)){
return true;
}
}
return false;
}



private String formatBody(String body, String contentType) {
if (contentType != null && contentType.toLowerCase().contains("json")) {
return FormatUtils.formatJson(body);
Expand Down
Loading