XMLHttpRequest Sending GET Request When Opening with POST - javascript

I am writing a basic function on my webpage, to POST data to another page on my webserver, however whenever I submit using this function, the server reports having received a GET request with no form data.
Unfortunately, I am completely at a loss when it comes to sorting this out, as I have no clue what is causing it.
function submit_function(event){
event.preventDefault();
var req = new XMLHttpRequest();
var fd = new FormData();
fd.append("username", "username");
fd.append("password", "password");
req.open("POST", "/auth/login", true);
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
req.send(fd);
return false;
}
Any help or insight at all is appreciated, it is getting late and there is a good chance I'm missing something obvious.
Issue was caused by a form submission interfering with the request, because it was nested as such.
document.getElementById("formid").onsubmit = function(e){ submit(e); }

The usual reason for this is that your code is triggered by a form submission, and you're not cancelling the form submission, so the browser sends the form (as a GET, apparently there's no type="POST" on the form element) and that prevents the ajax call from actually being made (even if your code runs to start it, tearing down the page to replace it with the result of the form submission prevents it from getting very far). Just ensure you're preventing the form submission (event.preventDefault()).

Related

JavaScript - send AJAX call on tab close (DELETE request)

I want to send an AJAX DELETE request through Javascript when the user closes the tab. The flow is the following:
When the user attempts to close the tab, a onbeforeunload event takes place, then if the user confirms to leave the page the onunload event takes place and tries to execute the deleteRequest function, which is a synchronous ajax delete request.
window.onbeforeunload = function(){
return 'Are you sure you want to leave?';
};
window.onunload = function(){
deleteRequest();
};
function deleteRequest(){
let url = new URL("http://......");
let request = new XMLHttpRequest();
request.onreadystatechange = function () {
if(request.readyState == 4){
if(request.status === 200){
console.log('success');
}
}
}
request.open("DELETE", url, false);
try{
request.send();
}
catch(e){
console.log(e);
}
}
Unfortunately, it seems that Google Chrome does not support anymore this since when a tab closes it kills all the pending events, and in the console of the browser I can see the following message
DOMException: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://.....': Synchronous XHR in page dismissal. See https://www.chromestatus.com/feature/4664843055398912 for more details.
at deletRequest(.......js:411:17)
at window.onunload
Please note that I have already seen many topics on this issue before on SO but the solutions did not really help since most of them are out of date since the policy of chrome on this changed quite recently, like this or this.
It seems that most people propose navigator.sendBeacon to achieve this, but in the documentation I saw only ways to make a POST request using this, any thoughts? Thanks in advance.
You're pretty much SOL as far as using sendBeacon out of the box goes, as PUT and DELETE cannot be sent as you observed (only POST). For your XMLHttpRequest, Chrome is very explicit about saying, "hey, we used to send these synchronous XHR requests in beforeunload if you used a no-op loop, but we're not supporting that anymore":
Failed to execute 'send' on 'XMLHttpRequest' [...] Synchronous XHR in page dismissal.
Chrome is intentionally disallowing this behavior. You have no option except to modify the backend, i.e., set up an endpoint that will receive sendBeacon POST request like https://example.com/trigger-delete/ and trigger the DELETE call from the backend, or, if it's not your server, you'll actually have to set up a relay server you control to receive the POST (https://myrelay.com/forward-delete/)and then pass it along as a DELETE.
sendBeacon is the only way you're getting out of this, as far as I can tell.

How to attach form data in url which is used by Ajax?

So, I came across this problem whereby I want to access the data of a website, but it works only after the user interacts with the website. So, after selecting the date, it sends the ajax request to its site with a url, but also the form data. Here is the screenshot taken in Google Chrome.
And the problem is, the url doesn't work without specifying the cdate parameter as highlighted in the picture. Is there any way, I can send the form data (cdate in our case) to the specified url, so that it doesn't lead me to the error? Any way to do that?
In order to send form data progmatically, you can use the FormData object like so:
var formData = new FormData();
formData.append("cdate", "09/14/2019");
var request = new XMLHttpRequest();
request.open("POST", "http://example.com");
request.send(formData);
request.onLoad => (e) {
// Do something with request.response
};
Adapted from https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects

ajax code returning ProgressEvent object rather than my template data

I'm trying to improve the UX on a few pages by adding some ajax. I have an ajax request:
var xhr = new XMLHttpRequest();
xhr.open('POST', '/search/', true);
xhr.onload = function(data){
document.getElementById("search-results-container").innerHTML = data;
}
xhr.setRequestHeader("X-CSRFToken", csrftoken);
xhr.send(form_data);
This isn't giving me the rendered template from my django development server. Instead I get [object ProgressEvent] in my #search-results-container div. The django view renders correctly if I submit the request synchronously.
I'm probably completely misunderstanding the spec, but aren't I supposed to get the template data + http headers straight back from the server? What have I done wrong here?
The event handlers for XHR events are passed event objects. Newer browsers support the ProgressEvent API. Those won't give you the data from the request, however; for that you'll need to retain access to the XHR object itself. The .responseText and (if appropriate) the .responseXML properties will contain your response content once the HTTP request has actually completed (which, in your "load" handler, it will have).

jQuery submit preventDefault

I load a page from example.com on port 80, then from the loaded page, submit a form to the same server on a different port (as defined in the form action attribute).
(html)
<form id="enabledForm" action="http://example.com:39991/updateEnabled" method="POST">
(javascript)
$('#enabledForm').submit()
This works fine and the data is delivered as expected to the form action url, but the browser is redirected to the address of the POST request instead of staying on the requesting page.
If I use
$('#enabledForm').submit(function (event) {
event.preventDefault();
});
or
$('#enabledForm').submit(function (event) {
return false;
});
then the server receives no data but the page is not redirected.
if I add an alert within the event handler then the alert is not shown.
$('#enabledForm').submit(function (event) {
alert('inside submit event handler');
return false;
});
Clearly I'm soing something wrong but after hours of headbanging and trying everything I can think of I'm stuck.
What to do?
You have two basic options here:
Have the server return a 204 No Content response and forget about using JS entirely
Prevent the submission of the form with JS and send the data to the URL with Ajax instead
No content:
If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent.
How you set the HTTP response status code depends on your server side language / framework. For example:
In Catalyst it would be something like:
$c->response->status(204);
In PHP it would be:
http_response_code(204);
There are many Ajax tutorials out there, so I'm not going to provide another one. The jQuery documentation has a detailed section on Ajax.
Note that since you are working across origins (different ports), you will need to circumvent the Same Origin Policy. The standard way to do that is with CORS.
Sending a form would automatically change your browser URL (and refresh view).You should use an Ajax request to send informations to your server and eventually retrieve completion (success, error, informations...).
Extract your inputs' values to an object via Jquery and send your request via Jquery.post or Jquery.get
$('#enabledForm').submit(function (event) {
//Prevent natual post
event.preventDefault();
//Retrieve inputs values
var data = {}
$('#enabledForm input,textarea').each(function(index){
data[$(this).attr('name')] = $(this).val();
});
//Send request
$.post('http://example.com:3999/updateEnabled',data,function(response){
//Parse response if you want to inform user about success of operation
});
});
I don't know if val() is usable with all of yout inputs, but it's easy to adapt...

XHR IE7 Operation Aborted JSON Error

I'm trying to send an AJAX post request in IE 7, but I'm getting an "Operation Aborted" error, seemingly from the JSON I'm sending, even though everything seems right. I've been messing around with this for an hour or so now, and haven't made any progress, so thought I would post it here to see if anyone could see anything wrong with it.
The "Operation Aborted" error keeps mentioning DOM loading issues, but I only see it when I try to make this post request, so I imagine it's something different in this situation.
var request = new XMLHttpRequest();
request.open("POST", url, false);
request.setRequestHeader("Content-Type", "application/json");
try {
request.send('{"param":"value"}');
} catch (e) {
alert(e.message);
}
It might be that the URL your trying to post data to simply doesn't work on IE7. Try updating to IE8.
http://support.microsoft.com/kb/927917
Stuff like this happens when a script tries to alter an element that hasn't finished loading yet. This website explains it quite well:
http://blogs.msdn.com/b/ie/archive/2008/04/23/what-happened-to-operation-aborted.aspx
changing request.send('{"param":"value"}'); to request.send('{ "param" : "value" }') fixed the issue, sigh.

Categories