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
Added support for a maximum content length property. The property rep… #12
Conversation
…resents a threshold for content that should be saved verbatim, or not.
@@ -52,6 +52,7 @@ | |||
private Context context; | |||
private NotificationHelper notificationHelper; | |||
private boolean showNotification; | |||
private int maxContentLength = Integer.MAX_VALUE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this field will be compared against a Long (transaction.getRequestContentLength
), shouldn't this field also be a long with default value Long.MAX_VALUE?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I'll fix that right now.
} | ||
} | ||
if (isPlaintext(buffer)) { | ||
transaction.setResponseBody(buffer.clone().readString(charset)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this would work, but instead of ignoring the response all together (due to it being too big), couldn't you try to truncate it instead to the bytes specified by maxContentLength
, via buffer.clone().readString(maxContentLength, charset)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about doing that, but that would essentially create malformed JSON. So when the FormatUtils.formatJson() runs to try to "pretty up" the JSON for display, it's probably going to barf.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @joaocsousa that truncating the response is a better approach. The formatting methods shouldn't barf, they'll just return the original text if there are parsing errors, and it would greatly simplify this change.
If we created a method like this:
private String readFromBuffer(Buffer buffer, Charset charset) {
long bufferSize = buffer.size();
long maxBytes = Math.min(bufferSize, maxContentLength);
String body = buffer.readString(maxBytes, charset);
if (bufferSize > maxContentLength) {
body += "\n\n--- Content truncated ---";
}
return body;
}
then it could simply be called where we set the request and response body on the transaction, and there's no need to store these requestBodyIsTooBig
and responseBodyIsTooBig
fields in the database. Everything else would work as is.
Thanks! I've finally got my mock web server setup to send responses large enough to break things, so I will look at this as soon as possible. I looks like it is Android's CursorWindow that breaks first, whose hard limit is 2048 KB. |
@joaocsousa @jgilfelt Thanks for the review. I've made the switch from Integer to Long per joaocsuousa's recommendation. I've responded to the other callout (whether or not to keep the partial result). |
Fixed the merge conflicts as well. |
@@ -74,6 +74,7 @@ | |||
private NotificationHelper notificationHelper; | |||
private RetentionManager retentionManager; | |||
private boolean showNotification; | |||
private long maxContentLength = Long.MAX_VALUE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should set a conservative default value that will ensure we don't exceed the platform limits, and let users increase it if they need to. We know the CursorWindow limit is 2 MB, but even at that size, I found that a response may still cause ANR issues when displayed with TextView, and potentially consume the application's Java heap space.
I think 250000
is a good default that will be suitable for most apps, and ensures things wont break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
* @param max the max length for request/response content. | ||
* @return The {@link ChuckInterceptor} instance. | ||
*/ | ||
public ChuckInterceptor maxContentLength(long max) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to shadow any methods that are public API in the corresponding class within the library-no-op
module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
} | ||
} | ||
if (isPlaintext(buffer)) { | ||
transaction.setResponseBody(buffer.clone().readString(charset)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @joaocsousa that truncating the response is a better approach. The formatting methods shouldn't barf, they'll just return the original text if there are parsing errors, and it would greatly simplify this change.
If we created a method like this:
private String readFromBuffer(Buffer buffer, Charset charset) {
long bufferSize = buffer.size();
long maxBytes = Math.min(bufferSize, maxContentLength);
String body = buffer.readString(maxBytes, charset);
if (bufferSize > maxContentLength) {
body += "\n\n--- Content truncated ---";
}
return body;
}
then it could simply be called where we set the request and response body on the transaction, and there's no need to store these requestBodyIsTooBig
and responseBodyIsTooBig
fields in the database. Everything else would work as is.
@jgilfelt Saw your change requests. I'll knock that out tomorrow and hit you back. |
I have addressed the feedback you guys gave me:
With maxContentLength left at its default value: With maxContentLength set to 5 (for testing): |
@eschlenz Nice work! I've just updated the method comment to reflect the new truncation behaviour. Thanks for putting this together so quickly. |
@jgilfelt No problem! Happy to help. |
…resents a threshold for content that should be saved verbatim, or not.
@jgilfelt
WHAT: This PR introduces a "max content length" property to the
ChuckInterceptor
. A request or response body that exceeds the new property's value will not be recorded. That is, there will still be a record of the transaction, but the content itself is not kept.WHY: Chuck was crashing on me when I would try to go to the Chuck UI. I determined that the saved response body for a few of my requests were simply too large for SQLite to handle. In such scenarios, I still want to see the transaction in the log. I don't need to see the content however. It made sense to apply this new max content length property to requests as well.
The max content length property is essentially disabled by default (set to Integer.MAX_VALUE). The user can optionally set a max length that works for them.
MISC: I tried to stick with the existing code conventions. Thanks for putting this tool together. It's very handy.