-
Notifications
You must be signed in to change notification settings - Fork 27.5k
feat(errorHandlingConfig): make the length of URL refrence in error m… #15707
Conversation
1ba0811
to
d99824f
Compare
…essages configurable Closes angular#14744 Closes angular#15707
d99824f
to
6136d59
Compare
…essages configurable Closes angular#14744 Closes angular#15707
6136d59
to
d861b50
Compare
…essages configurable Closes angular#14744 Closes angular#15707
d861b50
to
5ea7b0f
Compare
…essages configurable Closes angular#14744 Closes angular#15707
5ea7b0f
to
48e0b69
Compare
…essages configurable Closes angular#14744 Closes angular#15707
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.
Don't we have tests for errorHandlingConfig()
? 😱
Can you add them?
src/Angular.js
Outdated
@@ -152,12 +154,19 @@ var minErrConfig = { | |||
* * `objectMaxDepth` **{Number}** - The max depth for stringifying objects. Setting to a | |||
* non-positive or non-numeric value, removes the max depth limit. | |||
* Default: 5 | |||
* | |||
* * `urlMaxLength` **{Number}** - The max length of the URL reference in the error messages, it can be any number more than or equal 200. Setting to a |
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.
This like is too long. Also, why a 200 limit?
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 there is no good reason for the 200 limit. Let's remove it.
And then we can reuse isValidObjectMaxDepth()
for both validations (under a different, more generic name 😉).
@@ -143,6 +144,7 @@ var minErrConfig = { | |||
* current configuration if used as a getter. The following options are supported: | |||
* | |||
* - **objectMaxDepth**: The maximum depth to which objects are traversed when stringified for error messages. | |||
* - **urlMaxLength**: The maximum length of the URL reference in the error messages. |
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.
Please add a note explaining the consequences this will have to longer URLs (e.g. will they break? will they lack information? will the stack traces be truncated?)
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.
Restricting this will definitely mess with the error parsing in the docs app. I was wondering if we should additionally to objectMaxDepth have arrayMaxLength? Because when you have an array with 1000 objects, then objectMaxDepth isn't going to help your shortening the error output
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.
Limiting the array length makes sense (although not directly related to this PR).
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.
The problem is that each parameter value is encoded using encodeURIComponent
so when slice this encoded value it become invalid for some cases.
for (i = 0, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
url += paramPrefix + 'p' + i + '=' + encodeURIComponent(templateArgs[i]);
if (url.length > minErrConfig.urlMaxLength) {
url = url.substr(0, minErrConfig.urlMaxLength - 3) + '...';
break;
}
}
for example:
This link produced when i set urlMaxLength to 400
http://errors.angularjs.org/1.6.3-local+sha.48e0b69/$injector/modulerr?p0=n…cies%20as%20the%20second%20argument.%0Ahttp%3A%2F%2Ferrors.angularjs.org%2...
it look like it turn into
https://docs.angularjs.org/error/$injector/modulerr?p0=undefined
I will try to find a solution that slice the url without harming the encoded data.
src/minErr.js
Outdated
url = url.slice(0, minErrConfig.urlMaxLength - URL_MAX_LENGTH_END.length); | ||
url += URL_MAX_LENGTH_END; | ||
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.
This seems more complex than necessary :confused. I wonder if we could simplify the implementation.
test/minErrSpec.js
Outdated
return message.slice(urlStartAt); | ||
} | ||
|
||
function createDummyString(size) { |
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 don't think we need a helper for this. IIRC, we use new Array(size).join('a')
elsewhere in the tests.
test/minErrSpec.js
Outdated
var myError = testError('26', 'a when default=2000 is {0}', a); | ||
var url = extractUrlFromErrorMessage(myError.message); | ||
expect(url.length).toBe(2000); | ||
expect(errorHandlingConfig().urlMaxLength).toBe(2000); |
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.
No need for these assertions (here and below).
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.
These assertions are important to test that the default value is 2000 and doesn't change.
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 essentially testing two different things: errorHandlingConfig
and minErr
.
There should be different tests about errorHandlingConfig
, that verify that it works. Then here, you don't need to verify that. Just that minErr works as expected
There are tests for 'errorHandlingConfig' it('should slice error reference URL in the message if it exceeds url max length', function() {
var a = createDummyString(2000);
var myError = testError('26', 'a when default=2000 is {0}', a);
var url = extractUrlFromErrorMessage(myError.message);
expect(url.length).toBe(2000);
expect(errorHandlingConfig().urlMaxLength).toBe(2000);
errorHandlingConfig({urlMaxLength: 500});
myError = testError('26', 'a when urlMaxLength=500 is {0}', a);
url = extractUrlFromErrorMessage(myError.message);
expect(url.length).toBe(500);
expect(errorHandlingConfig().urlMaxLength).toBe(500);
errorHandlingConfig({urlMaxLength: undefined});
myError = testError('26', 'a when urlMaxLength=undefined is {0}', a);
url = extractUrlFromErrorMessage(myError.message);
expect(url.length).toBe(500);
expect(errorHandlingConfig().urlMaxLength).toBe(500);
});
they('should ignore url max length when urlMaxLength = $prop',
[NaN, null, true, false, -1, 0], function(maxLength) {
errorHandlingConfig({urlMaxLength: maxLength});
var a = createDummyString(2100);
var myError = testError('26', 'a is {0}', a);
var url = extractUrlFromErrorMessage(myError.message);
expect(url.length).toBeGreaterThan(2100);
expect(errorHandlingConfig().urlMaxLength).toBeNaN();
}
); Do you mean to create a separate test for errorHandlingConfig? and the same will be for objectMaxDepth. describe('errorHandlingConfig', function(){
it('should the default urlMaxLength be 2000', function(){
expect(errorHandlingConfig().urlMaxLength).toBe(2000);
};)
it('should set urlMaxLength', function(){
errorHandlingConfig({urlMaxLength:3000});
expect(errorHandlingConfig().urlMaxLength).toBe(3000);
});
they('should set urlMaxLength to be NAN when it is setting to $prop',
[false, true, -1, null, NAN], function(maxLength){
errorHandlingConfig({urlMaxLength: maxLength});
expect(errorHandlingConfig().urlMaxLength).toBeNAN();;
});
}); |
Yes. We should have tests for
|
48e0b69
to
0e1cfce
Compare
…essages configurable Closes angular#14744 Closes angular#15707
0e1cfce
to
4d5d1df
Compare
…essages configurable Closes angular#14744 Closes angular#15707
4d5d1df
to
93fe2cf
Compare
…essages configurable Closes angular#14744 Closes angular#15707
93fe2cf
to
9bf1bdd
Compare
…essages configurable Closes angular#14744 Closes angular#15707
9bf1bdd
to
82e1893
Compare
|
||
if (url.length > minErrConfig.urlMaxLength) { | ||
url = url.substr(0, minErrConfig.urlMaxLength - 3) + '...'; | ||
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.
@gkalpak
I feel it is confusing too, if we set urlMaxlength to 1000, then it will substr(0, 997) since it will add '...'
So the max length become 997 not 1000.
Should I remove '...' ? but still need something to tell that this is not the full url.
Should I substr(0, 1000) then add '...' and handle this in the unit test by asserting it to equal 1003
Do you have any suggestion ?
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.
The ...
(or whatever we choose to indicate the URL was truncated) is not actually part of the URL. So, it shouldn't count against its length.
I suggest, you don't take it into account when calculating the URL length. And instead of appending ...
(which might not be clear), I suggest we add soething like (truncated URL)
right after.
…essages configurable Closes angular#14744 Closes angular#15707
If we cannot truncate the url reliably, can we truncate the stack instead? This means we won't know exactly how long the url is, but this isn't really needed anyway. We just want a url that has a managable size. |
So, it turns out the error stack is not an explicit parameter to the minErr. It simply gets added whenever throwing a minErr triggers another minErr. A common cause is when you include a module that doesn't exist: this triggers "nomod" and then "modulerr", i.e. modulerr includes the message (good) and stack (bad) of nomod, e.g. this error url So we cannot say "truncate only the stack", but we can say "truncate all error template arguments", which will sometimes include the stack of another error. We could also allow urlArgsMaxLength=0 and then remove the part with the parameters completely, as proposed in #16283 Here's a PoC: In Chrome you get a "nice" stack which is the moderr, and then for some reason 4 times the same modulerr. In Firefox, it's just a giant blob that is not even clickable (but that is the default behavior). So by restricting the argument length, it becomes a bit better (and the urls actually work), but the stacks can still be confusing. |
I think that PR #16283 has a better solution than this PR |
Specific errors, such as nested module loading, can create very long error urls because they include the error stack. These urls create visual clutter in the browser console, are often not clickable, and may be rejected by the docs page because they are simply too long. We've already made improvements to the error display in angular#16283, which excludes the error url from error parameters, which results in cleaner error messages. Further, modern browsers restrict console message length intelligently. This option can still be useful for older browsers like Internet Explorer, or in general to reduce visual clutter in the console. Closes angular#14744 Closes angular#15707 Closes angular#16283 Closes angular#16299
Specific errors, such as those during nested module loading, can create very long error urls because the error message includes the error stack. These urls create visual clutter in the browser console, are often not clickable, and may be rejected by the docs page because they are simply too long. We've already made improvements to the error display in #16283, which excludes the error url from error parameters, which results in cleaner error messages. Further, modern browsers restrict console message length intelligently. This option can still be useful for older browsers like Internet Explorer, or in general to reduce visual clutter in the console. Closes #14744 Closes #15707 Closes #16283 Closes #16299 Closes #16591
Specific errors, such as those during nested module loading, can create very long error urls because the error message includes the error stack. These urls create visual clutter in the browser console, are often not clickable, and may be rejected by the docs page because they are simply too long. We've already made improvements to the error display in #16283, which excludes the error url from error parameters, which results in cleaner error messages. Further, modern browsers restrict console message length intelligently. This option can still be useful for older browsers like Internet Explorer, or in general to reduce visual clutter in the console. Closes #14744 Closes #15707 Closes #16283 Closes #16299 Closes #16591
…essages configurable
Closes #14744
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Feature
What is the current behavior? (You can also link to an open issue here)
Sometimes AngularJS throw error with long messages, very long URL referenced error
Will cause 414 Request-URI Too Large as in Issue #14744
What is the new behavior (if this is a feature change)?
make the Url reference error length configurable.
Does this PR introduce a breaking change?
NO
Please check if the PR fulfills these requirements
Other information:
Microsoft Internet Explorer has a maximum uniform resource locator (URL) length of 2,083 characters. Internet Explorer also has a maximum path length of 2,048 characters. This limit applies to both POST request and GET request URLs. https://support.microsoft.com/en-us/help/208427/maximum-url-length-is-2,083-characters-in-internet-explorer which is less than all the other browsers, so i added the default value for url max length to be 2000 characters.
I don't know what should be the minimum length for URL reference error but i implemented it with a constrains to be more than 200.