How to get stack traces for XHR calls in a browser? - javascript

Is there some way that I can get stack traces in a browser every time an HTTP request is made? I'm using Chrome dev tools, but I'll use a different tool, if there is one that can do this.
I suppose I could monkeypatch XMLHttpRequest to throw an error, but that is a fairly awkward solution.
I am trying to determine why an HTTP request was made, and being able to identify a high level function that led to that request would really help.

If you are using firefox then use Firebug plugin.
In firebug, you can easily see the stack of HTTP calls.
You can easily see javascript code a put a breakpoint. when debugger stops on breakpoint, it shows the stack of operation it has done to reach till there.
Read Firebug Tutorial

You can remove the XMLHttpRequest support from browser by setting it undefined:
XMLHttpRequest = undefined
Then it will fail any time you try to use it - and throw an error you can use for the stack.
Or better replace send() method with own that will get the stack:
XMLHttpRequest.prototype.send = function() {
try {
crash.me.now(); //make sure this is undefined
}
catch(err) {
console.error(err.stack || err.stacktrace || err.stackTrace);
}
}

In Chrome devtools there is an options to set a "XHR breakpoint".
Once the send() request is fired, the code halts, the breakpoint is hit and then you can see the stacktrace normally similar to using code breakpoints.

In chrome dev tools, you can see something like this if you capture a timeline activity.
First, open the dev tools, then go to "timeline" tab. It should be asking you to capture timeline. Hit ctrl-E and reload the page. After the page has loaded, press "finish" button.
Then go to the "network" tab, click on the ajax request you want to look at. At this point you should check that you have the overview visible: just below the tabs line, there is part that says "View:" and there you should toggle Overview on if it's not already.
Now you can select that part on the overview with your mouse like you were selecting text. Select the part of overview that has your ajax request.
Now, switch to the "timeline" tab. Make sure that on the "View" part you have toggled "flamechart" on. Now, there should be the javascript function calls visible. Unfortunately it seems that the names of function calls are truncated to an optimized form, but there are at least links to the js files that have those functions. Anyways, the topmost of the stack you are seeing should be the Event that triggered the XMLHttpRequest call.

Related

How can I cancel consecutive requests to my server? [duplicate]

What would cause a page to be canceled? I have a screenshot of the Chrome Developer Tools.
This happens often but not every time. It seems like once some other resources are cached, a page refresh will load the LeftPane.aspx. And what's really odd is this only happens in Google Chrome, not Internet Explorer 8. Any ideas why Chrome would cancel a request?
We fought a similar problem where Chrome was canceling requests to load things within frames or iframes, but only intermittently and it seemed dependent on the computer and/or the speed of the internet connection.
This information is a few months out of date, but I built Chromium from scratch, dug through the source to find all the places where requests could get cancelled, and slapped breakpoints on all of them to debug. From memory, the only places where Chrome will cancel a request:
The DOM element that caused the request to be made got deleted (i.e. an IMG is being loaded, but before the load happened, you deleted the IMG node)
You did something that made loading the data unnecessary. (i.e. you started loading a iframe, then changed the src or overwrite the contents)
There are lots of requests going to the same server, and a network problem on earlier requests showed that subsequent requests weren't going to work (DNS lookup error, earlier (same) request resulted e.g. HTTP 400 error code, etc)
In our case we finally traced it down to one frame trying to append HTML to another frame, that sometimes happened before the destination frame even loaded. Once you touch the contents of an iframe, it can no longer load the resource into it (how would it know where to put it?) so it cancels the request.
status=canceled may happen also on ajax requests on JavaScript events:
<script>
$("#call_ajax").on("click", function(event){
$.ajax({
...
});
});
</script>
<button id="call_ajax">call</button>
The event successfully sends the request, but is is canceled then (but processed by the server). The reason is, the elements submit forms on click events, no matter if you make any ajax requests on the same click event.
To prevent request from being cancelled, JavaScript event.preventDefault(); have to be called:
<script>
$("#call_ajax").on("click", function(event){
event.preventDefault();
$.ajax({
...
});
});
</script>
NB: Make sure you don't have any wrapping form elements.
I had a similar issue where my button with onclick={} was wrapped in a form element. When clicking the button the form is also submitted, and that messed it all up...
Another thing to look out for could be the AdBlock extension, or extensions in general.
But "a lot" of people have AdBlock....
To rule out extension(s) open a new tab in incognito making sure that "allow in incognito is off" for the extention(s) you want to test.
In my case, I found that it is jquery global timeout settings, a jquery plugin setup global timeout to 500ms, so that when the request exceed 500ms, chrome will cancel the request.
You might want to check the "X-Frame-Options" header tag. If its set to SAMEORIGIN or DENY then the iFrame insertion will be canceled by Chrome (and other browsers) per the spec.
Also, note that some browsers support the ALLOW-FROM setting but Chrome does not.
To resolve this, you will need to remove the "X-Frame-Options" header tag. This could leave you open to clickjacking attacks so you will need to decide what the risks are and how to mitigate them.
Here's what happened to me: the server was returning a malformed "Location" header for a 302 redirect.
Chrome failed to tell me this, of course. I opened the page in firefox, and immediately discovered the problem.
Nice to have multiple tools :)
Another place we've encountered the (canceled) status is in a particular TLS certificate misconfiguration. If a site such as https://www.example.com is misconfigured such that the certificate does not include the www. but is valid for https://example.com, chrome will cancel this request and automatically redirect to the latter site. This is not the case for Firefox.
Currently valid example: https://www.pthree.org/
A cancelled request happened to me when redirecting between secure and non-secure pages on separate domains within an iframe. The redirected request showed in dev tools as a "cancelled" request.
I have a page with an iframe containing a form hosted by my payment gateway. When the form in the iframe was submitted, the payment gateway would redirect back to a URL on my server. The redirect recently stopped working and ended up as a "cancelled" request instead.
It seems that Chrome (I was using Windows 7 Chrome 30.0.1599.101) no longer allowed a redirect within the iframe to go to a non-secure page on a separate domain. To fix it, I just made sure any redirected requests in the iframe were always sent to secure URLs.
When I created a simpler test page with only an iframe, there was a warning in the console (which I had previous missed or maybe didn't show up):
[Blocked] The page at https://mydomain.com/Payment/EnterDetails ran insecure content from http://mydomain.com/Payment/Success
The redirect turned into a cancelled request in Chrome on PC, Mac and Android. I don't know if it is specific to my website setup (SagePay Low Profile) or if something has changed in Chrome.
Chrome Version 33.0.1750.154 m consistently cancels image loads if I am using the Mobile Emulation pointed at my localhost; specifically with User Agent spoofing on (vs. just Screen settings).
When I turn User Agent spoofing off; image requests aren't canceled, I see the images.
I still don't understand why; in the former case, where the request is cancelled the Request Headers (CAUTION: Provisional headers are shown) have only
Accept
Cache-Control
Pragma
Referer
User-Agent
In the latter case, all of those plus others like:
Cookie
Connection
Host
Accept-Encoding
Accept-Language
Shrug
I got this error in Chrome when I redirected via JavaScript:
<script>
window.location.href = "devhost:88/somepage";
</script>
As you see I forgot the 'http://'. After I added it, it worked.
Here is another case of request being canceled by chrome, which I just encountered, which is not covered by any of answers up there.
In a nutshell
Self-signed certificate not being trusted on my android phone.
Details
We are in development/debug phase. The url is pointing to a self-signed host. The code is like:
location.href = 'https://some.host.com/some/path'
Chrome just canceled the request silently, leaving no clue for newbie to web development like myself to fix the issue. Once I downloaded and installed the certificate using the android phone the issue is gone.
If you use axios it can help you
// change timeout delay:
instance.defaults.timeout = 2500;
https://github.com/axios/axios#config-order-of-precedence
For my case, I had an anchor with click event like
<a href="" onclick="somemethod($index, hour, $event)">
Inside click event I had some network call, Chrome cancelling the request. The anchor has href with "" means, it reloads the page and the same time it has click event with network call that gets cancelled. Whenever i replace the href with void like
<a href="javascript:void(0)" onclick="somemethod($index, hour, $event)">
The problem went away!
If you make use of some Observable-based HTTP requests like those built-in in Angular (2+), then the HTTP request can be canceled when observable gets canceled (common thing when you're using RxJS 6 switchMap operator to combine the streams). In most cases it's enough to use mergeMap operator instead, if you want the request to complete.
I had faced the same issue, somewhere deep in our code we had this pseudocode:
create an iframe
onload of iframe submit a form
After 2 seconds, remove the iframe
thus, when the server takes more than 2 seconds to respond the iframe to which the server was writing the response to, was removed, but the response was still to be written , but there was no iframe to write , thus chrome cancelled the request, thus to avoid this I made sure that the iframe is removed only after the response is over, or you can change the target to "_blank".
Thus one of the reason is:
when the resource(iframe in my case) that you are writing something in, is removed or deleted before you stop writing to it, the request will be cancelled
I have embedded all types of font as well as woff, woff2, ttf when I embed a web font in style sheet. Recently I noticed that Chrome cancels request to ttf and woff when woff2 is present. I use Chrome version 66.0.3359.181 right now but I am not sure when Chrome started canceling of extra font types.
We had this problem having tag <button> in the form, that was supposed to send ajax request from js. But this request was canceled, due to browser, that sends form automatically on any click on button inside the form.
So if you realy want to use button instead of regular div or span on the page, and you want to send form throw js - you should setup a listener with preventDefault function.
e.g.
$('button').on('click', function(e){
e.preventDefault();
//do ajax
$.ajax({
...
});
})
I had the exact same thing with two CSS files that were stored in another folder outside my main css folder. I'm using Expression Engine and found that the issue was in the rules in my htaccess file. I just added the folder to one of my conditions and it fixed it. Here's an example:
RewriteCond %{REQUEST_URI} !(images|css|js|new_folder|favicon.ico)
So it might be worth you checking your htaccess file for any potential conflicts
happened to me the same when calling a. js file with $. ajax, and make an ajax request, what I did was call normally.
In my case the code to show e-mail client window caused Chrome to stop loading images:
document.location.href = mailToLink;
moving it to $(window).load(function () {...}) instead of $(function () {...}) helped.
In can this helps anybody I came across the cancelled status when I left out the return false; in the form submit. This caused the ajax send to be immediately followed by the submit action, which overwrote the current page. The code is shown below, with the important return false at the end.
$('form').submit(function() {
$.validator.unobtrusive.parse($('form'));
var data = $('form').serialize();
data.__RequestVerificationToken = $('input[name=__RequestVerificationToken]').val();
if ($('form').valid()) {
$.ajax({
url: this.action,
type: 'POST',
data: data,
success: submitSuccess,
fail: submitFailed
});
}
return false; //needed to stop default form submit action
});
Hope that helps someone.
For anyone coming from LoopbackJS and attempting to use the custom stream method like provided in their chart example. I was getting this error using a PersistedModel, switching to a basic Model fixed my issue of the eventsource status cancelling out.
Again, this is specifically for the loopback api. And since this is a top answer and top on google i figured i'de throw this in the mix of answers.
For me 'canceled' status was because the file did not exist. Strange why chrome does not show 404.
It was as simple as an incorrect path for me. I would suggest the first step in debugging would be to see if you can load the file independently of ajax etc.
The requests might have been blocked by a tracking protection plugin.
It happened to me when loading 300 images as background images. I'm guessing once first one timed out, it cancelled all the rest, or reached max concurrent request. need to implement a 5-at-a-time
One the reasons could be that the XMLHttpRequest.abort() was called somewhere in the code, in this case, the request will have the cancelled status in the Chrome Developer tools Network tab.
In my case, it started coming after chrome 76 update.
Due to some issue in my JS code, window.location was getting updated multiple times which resulted in canceling previous request.
Although the issue was present from before, chrome started cancelling request after update to version 76.
I had the same issue when updating a record. Inside the save() i was prepping the rawdata taken from the form to match the database format (doing a lot of mapping of enums values, etc), and this intermittently cancels the put request. i resolved it by taking out the data prepping from the save() and creating a dedicated dataPrep() method out of it. I turned this dataPrep into async and await all the memory intensive data conversion. I then return the prepped data to the save() method that i could use in the http put client. I made sure i await on dataPrep() before calling the put method:
await dataToUpdate = await dataPrep();
http.put(apiUrl, dataToUpdate);
This solved the intermittent cancelling of request.

How do I test that Sentry is reporting errors?

I just installed Sentry for a client-side JavaScript app using the standard code snippet they provided. How do I test that it's working properly? I've tried manually throwing an error from my browser console and it didn't appear in Sentry. Is there any documentation on the right way to do this?
Verify (newer)
myUndefinedFunction();
Verifying Your Setup (older)
Sentry.captureException(new Error("This is my fake error message"));
https://docs.sentry.io/platforms/javascript/?platform=browser#verifying-your-setup
May be worth double-checking your setup (or updating) and config too.
The browser console can not be used as it is sandboxed. A simple trick is to attach the code to an HTML element like this:
<h1 onClick="throw new Error('Test')">
My Website
</h1>
And click on the heading afterwards.
This can be done in the browser inspector and so your source code doesn't have to be modified.
One way to generate an error in Sentry is to call a function that is not defined.
Note: This cannot be done in the console - it must be in the code.
Try adding this to your code (taken from the docs):
myUndefinedFunction();
If your code build doesn't allow this due to tests/linting you might be able to use:
window.myUndefinedFunction()
You should then see error in your browser console and in the Sentry dashboard.
Have a read of the Docs for more info.
Raven.captureMessage('Broken!') is a good place to start (also pulled from Sentry docs). If that fails to send, the Raven client isn't being initiated.
If you can't or don't want to use an undefined function to test Sentry is sending errors, you can also use the Debugger in Chrome's DevTools by:
Adding a breakpoint in your code e.g. for a click event handler
Trigger that event e.g. click a button
When the breakpoint hits in the console, set a function/variable that is needed for execution to undefined
Press play/continue in DevTools to then see the Error output
e.g.
1: function onClick() {
2: api.sendSomeEvent();
3: }
Add a breakpoint in the body of the onClick event handler (Line 2), trigger the event. When execution is paused: in your console enter something like api = undefined and hit enter to update the state. Then continue execution (click the play button), where you should see an error (ala api is undefined) that Sentry should then send for you.
Note: this works for any environment, though you may need to be clever with finding your events in minified code ;)

Capturing JS errors in Chrome

I'm capturing js errors in the application with window.onerror, but the thing is - in Chrome if dev tools isn't opened - then the url parameter passed to onerror handler always equals to the opened url.
While if dev tools is opened - then the url points to the exact .js file the caused the js error.
How do you deal with it? Are there any workarounds?
And to be more clear - here are 2 results:
Uncaught ReferenceError: a is not defined index:122 - this was received after fetching a page
Uncaught ReferenceError: a is not defined List.js:122 - this was received after fetching the same page with dev tools opened. This is an expected result - I've put a(); call to the List.js file for testing.
UPD: this is done for functional testing (using selenium webdriver) - I want to capture js errors for further investigations.
Let's pose the following architecture:
window.addEventListener("error", handleException, false);
function handleException(I_sMsg) {
if (I_sMsg.stack) {
sMsg = I_sMsg.stack.replaceAll(getBaseURL(), "");
alert(sMsg);
} else if (I_sMsg.message) {
alert(I_sMsg.message);
}
return cancelEvent(I_sMsg);
}
Now any throw new Error("description"); will go through the first part of the if statement and have a nice stack for you to parse with the urls.
It also works for unexpected exceptions, having as a result the following message (in this case after calling the unexisting bibi() function)
After further investigation, my framework is using some kind of home made job management (as shown in the stack actually) where every single action belongs to a job.
The job execution method is the following (simplified)
try {
oTask.func.apply(oTask.obj, oTask.prms);
} catch(ex) {
handleException(ex);
return false;
}
So it means every single execution is encapsulated within this single try catch block. As you see, the exception is caught, and passed to the handler. Not the error.
I though it was working in the other file but it was because the call was encapsulated, while within the api.js file directly it was a free call not managed by the framework.
More of a something to try answer really but it might help.
Chrome recently added chrome://inspect/ to the list of handy URLs (see chrome://chrome-urls/ for the complete list). I cannot find the tweet or blog post I read about this unfortunately but I think it was within the last month. The URL works on Chrome 28 for sure.
chrome://inspect/ lists all open tabs with an inspect link which redirects back to the existing open page but also opens DevTools.
I'm thinking that the selenium test could open the site under test in one tab and in a second tab open the inspect page, follow the inspect link back to the test page but this time with DevTools open, allowing window.onerror to capture better errors.
Something like:
document.getElementsByClassName('row')[n].getElementsByTagName('a')[0].click()

Under IE8, Page_Init isn't getting called

We've got a site where we Response.Redirect to a page (the cart page) and for some reason, the Page_Init and Page_Load functions aren't being called for that page when using IE8. Even if I put the cursor in the URL Bar and hit enter, they still aren't getting called. When I hit F5, it gets called. When I use another browser (including IE9 in IE8 mode), they get called. I ran Fiddler2 to inspect the traffic and no traffic occurs when I click on the URL bar and hit enter even though you see the world icon spin and it seems to be doing stuff for a 1/2 second.
What could cause this behavior? Seems like it has to be Javascript and/or an Update Panel that's intercepting the Page_Load.
Specifics: The site is an AbleCommerce and the page is the cart page. We've customized the product selection process.
I'm able to replicate the problem on our test instance of the site so I added Breakpoints to both the Page_Init and Page_Load functions of the custom control that loads the cart. Under IE8, I can put my cursor in IE8's url bar and hit enter and the breakpoints never get hit. Any other browser, they get hit. Running IE9 in IE8 Browser Mode, they get hit. But in IE8, they only get hit when I do a refresh (F5).
I'm thinking this has to be a Javascript or Update Panel issue. There are no Javascript errors showing in the Firefox Error console or in IE8.
Any thoughts on what might be causing this? Or how I can troubleshoot it?
Try to call your page with an extra parameter, like &_=xyz where xyz is always fresh (like the current time tostring). If the page is refreshed with an extra parameter, you have a caching issue where the browser caches too aggressively.
Why is could be so - it's hard to say. It could be a jquery issue where you call the url with full caching enabled and then the browser pick up the caching setting internally and never calls back your page.
The current accepted answer is a good way to debug this issue. But a better solution to this issue is that you should set the HTTP headers on the response to tell the browser that it should not cache it.
Take a look at the accepted answer for this Stack Overflow question to learn how to set the cache headers in most popular languages:
Making sure a web page is not cached, across all browsers
I had your exact same problem... It's because the heavy caché options in IE. So instead of using the random variable, I set all response cache to false en every postback like this:
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetNoStore();
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(DateTime.Now);
Response.Cache.SetLastModified(DateTime.Now);
Response.Cache.SetAllowResponseInBrowserHistory(false);
....
}
Source: Page_Load called in Firefox, but not IE

Where in JavaScript is the request coming from?

I am debugging a large, complex web page that has a lot of JavaScript, JQuery, Ajax and so on. Somewhere in that code I am getting a rouge request (I think it is an empty img) that calls the root of the server. I know it is not in the html or the css and am pretty convinced that somewhere in the JavaScript code the reqest is being made, but I can't track it down. I am used to using firebug, VS and other debugging tools but am looking for some way to find out where this is executed - so that I can find the offending line amongst about 150 .js files.
Apart from putting in a gazzillion console outputs of 'you are now here', does anyone have suggestions for a debugging tool that could highlight where in Javascript requests to external resources are made? Any other ideas?
Step by step debugging will take ages - I have to be careful what I step into (jQuery source - yuk!) and I may miss the crucial moment
What about using the step-by-step script debugger in Firebug ?
I also think that could be a very interesting enhancement to Firebug, being able to add a breakpoint on AJAX calls.
You spoke of jQuery source...
Assuming the request goes through jQuery, put a debug statement in the jQuery source get() function, that kicks in if the URL is '/'. Maybe then you can tell from the call stack.
You can see all HTTP request done through JavaScript using the Firebug console.
If you want to track all HTTP requests manually, you can use this code:
$(document).bind('beforeSend', function(event, request, ajaxOptions)
{
// Will be called before every jQuery AJAX call
});
For more information, see jQuery documentation on AJAX events.
If its a HTTPRequest sent to a web server, I would recommend using TamperData plugin on Firefox. Just install the plugin, start tamper data, and every request sent will be prompted to tamper/continue/abort first.
Visit this page at Mozilla website
Just a guess here, but are you using ThickBox? It tries to load an image right at the start of the code.
First thing I would do is check whether this rouge request is an Ajax request or image load request via the Net panel in Firebug.
If it's Ajax, then you can overload the $.ajax function with your own and do a strack trace and include the URL requested before handing off to the original $.ajax.
If it's an image, it's not ideal, but if you can respond to the image request with a server side sleep (i.e. php file that just sleeps for 20 seconds) you might be able to hang the app and get a starting guess as to where the problem might be.

Categories

Resources