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

Added support for a maximum content length property. The property rep… #12

Merged
merged 9 commits into from Feb 14, 2017

Conversation

eschlenz
Copy link
Contributor

@eschlenz eschlenz commented Feb 10, 2017

…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.

…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;

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?

Copy link
Contributor Author

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));
Copy link

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)?

Copy link
Contributor Author

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.

Copy link
Owner

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
Copy link
Owner

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.

@eschlenz
Copy link
Contributor Author

@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).

@eschlenz
Copy link
Contributor Author

Fixed the merge conflicts as well.

jgilfelt added a commit that referenced this pull request Feb 13, 2017
@@ -74,6 +74,7 @@
private NotificationHelper notificationHelper;
private RetentionManager retentionManager;
private boolean showNotification;
private long maxContentLength = Long.MAX_VALUE;
Copy link
Owner

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.

Copy link
Contributor Author

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) {
Copy link
Owner

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.

Copy link
Contributor Author

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));
Copy link
Owner

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.

@eschlenz
Copy link
Contributor Author

@jgilfelt Saw your change requests. I'll knock that out tomorrow and hit you back.

@eschlenz
Copy link
Contributor Author

@jgilfelt @joaocsousa

I have addressed the feedback you guys gave me:

  1. I have shadowed the maxContentLength function in the no-op library.
  2. I have removed the "content too big" properties that I had previously added to the HttpTransaction model.
  3. The content is now retained, but truncated if it is too long.
  4. I have set the default maxContentLength to a more reasonable (and logical) value of 250000L.

With maxContentLength left at its default value:

screen shot 2017-02-14 at 9 14 55 am

screen shot 2017-02-14 at 9 14 58 am

With maxContentLength set to 5 (for testing):

screen shot 2017-02-14 at 9 15 31 am

screen shot 2017-02-14 at 9 15 36 am

@jgilfelt jgilfelt merged commit 7cb8191 into jgilfelt:master Feb 14, 2017
@jgilfelt
Copy link
Owner

@eschlenz Nice work! I've just updated the method comment to reflect the new truncation behaviour. Thanks for putting this together so quickly.

@eschlenz
Copy link
Contributor Author

@jgilfelt No problem! Happy to help.

@eschlenz eschlenz deleted the hotfix/max_content_length branch February 14, 2017 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants