It is common to use HTTP method POST to send a form.
For example, if the form action is "/login",
the request would send to server, and the URL would be like "index/login".
However, I want to implement two things.
Use HTTP method POST without "form". I want to send my own message.
And without changing the URL after the AJAX
Thanks.
Update: reply to DvS
The studies I have researched use libraries like jQuery or AngularJS.
But I want to implement by pure javascript.(like XMLHTTPRequest)
And I don't know how to use "NOT A FORM" in AJAX.
Maybe there's some references I can study?
Thanks again.
Try jQuery's AJAX call
http://api.jquery.com/jquery.ajax/
$("#id_of_button_to_submit").click(function(){
$.ajax({url: "/login", success: function(result){
//do things with your result
$("#div1").html(result);
}});
});
I found answer in "You might need jQuery"
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var resp = request.responseText;
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
The server side is implemented by Node.js and express
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.post('/newindex', function(req, res){
console.log("req received!");
res.send('This is POST METHOD');
})
app.listen(8888);
Old post but I ran into this problem and it got to my search results, and I suspect that the cause is the same.
Basically don't use a form action and submit button.
Then call the function using a regular button, or whatever else you want.
Seems like default form behavior for the submit button but without an action is HTTP GET to the current page, which runs and of course mucks everything up.
Related
The following is an MCVE of my server.js code:
let fs = require('fs');
let http = require('http');
http.createServer((req, res) => {
// Handles GET requests
if(req.method == 'GET') {
let file = req.url == '/' ? './index.html': '/login.html'; // just an example
fs.readFile(file, (err, data) => {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data);
});
}
// Handles POST requests
else {
read(status => {
if(status) {
res.writeHead(302, {
'Location': 'http://localhost:8000/login.html',
'Content-Type': 'text/html'
});
res.end();
console.log('Redirected!');
}
});
}
}).listen(8000);
// In my actual script, the `read` function reads JSON files and sends data,
// so I've used the callback function
let read = callback => fs.readFile( './index.html', (err, data) => callback(true) );
And, I've two HTML files as mentioned inside the code.
index.html
<input type="submit" onclick='let xhr = new XMLHttpRequest(); xhr.open("POST", "http://localhost:8000"); xhr.send();'>
I've used inline script to minimize traffic in my MCVE. For development purposes, I'll be using external scripts on my website
login.html
<h1>Login</h1>
Now, when I open http://localhost, index.html shows up nicely. As you've noticed that index.html is just a button. So, when I click on that button, Ajax request is fired successfully and everything works fine (no console errors) EXCEPT the fact that page does not redirects. I don't know what it going wrong or what else is missing.
I'm a beginner in Node.js and read about redirection in Nodejs - Redirect url and How to redirect user's browser URL to a different page in Nodejs?, I've searched a lot but couldn't get a hint on this. Thanks for your time!
Also, I'm aware about express, but I don't consider use of frameworks as they hide core concepts.
EDIT: When I try redirecting without the callback concept, then it works fine, as this video tells us.
This is not an issue with node.js. It is just how browsers behave.
Ajax (XHR) does not trigger redirects in the browser. When browsers implemented XHR browser developers assumed you want control of the page refresh behaviour. Therefore they made sure XHR does not trigger any default action. All redirects will be silent and the resultant data of the redirect will be passed to your XHR object's onreadystatechange callback.
If you want redirects to trigger page refresh you can simply choose to not use XHR. Instead do a form submission:
<!-- index.html -->
<form action="http://localhost:8000" method="post">
<input type="submit">
</form>
If instead you want to use AJAX, you will need to do the redirect in the browser like I mentioned above:
// server.js
// ...
http.createServer((req, res) => {
// ...
// Handles POST requests
else {
read(status => {
if(status) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({
your_response: 'here'
}));
}
});
}
}).listen(8000);
Then handle that response in the browser:
index.html
<input type="submit" onclick='let xhr = new XMLHttpRequest();xhr.addEventListener("load", function(){var response = JSON.parse(this.responseText);/* check response if you need it: */if (response.your_response === 'here') {window.location.href = 'http://localhost:8000/login.html';}});xhr.open("POST", "http://localhost:8000");xhr.send();'>
But this is crazy ugly and almost impossible to read. I'd suggest refactoring that HTML to something like this:
<!-- index.html -->
<script>
function handleSubmit () {
let xhr = new XMLHttpRequest();
xhr.addEventListener("load", function(){
var response = JSON.parse(this.responseText);
/* check response if you need it: */
if (response.your_response === 'here') {
window.location.href = 'http://localhost:8000/login.html'; // REDIRECT!!
}
});
xhr.open("POST", "http://localhost:8000");
xhr.send();
}
</script>
<input type="submit" onclick="handleSubmit()">
You should be using express when dealing with node js web application unless you have an internal understanding of the current node version you are using a suggestion.
Express is simple and you code would look like this (and to redirect)
app.get('/index.html',function(req,res,next){
res.redirect('/path/to/redirect/file')
}
link:
http://expressjs.com/en/4x/api.html#res.redirect
I am creating a simple app using node, express, mysql.
I am trying to create a route with which I can delete a row from my db, I wrote a pure javascript xhr.
when I test it I keep getting the following error message
POST http://localhost:3000/article/22 404 (Not Found)
this is what I have:
main.js
function handleDeleteClick(e, userId) {
e.preventDefault(); // Prevent default behaviour of this event (eg: submitting the form
// Perform the AJAX request to delete this user
var target = e.target;
var id = target.getAttribute('data-id');
var page = '/article/' + id;
var parameters = 'delete=true';
var xmlhttp = new XMLHttpRequest();
if (confirm('Are you sure you want to delete this?') == true) {
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// Request completed
}
}
xmlhttp.open("POST", page, true);
xmlhttp.send(parameters);
}
}
and the route app.js
app.delete('/article/:id', function(req, res) {
con.query(`DELETE FROM posts WHERE posts.id = ${req.params.id}`,
function(err, result, fields) {
if (err) {
console.log(err);
} else {
console.log("deleted Record: " + result.affectedRows);
res.redirect('/')
}
});
});
what am I missing?
help is very much appreciated!
thanks.
change POST to DELETE in your main.js-file:
xmlhttp.open("DELETE", page, true);
You are getting this 404 NOT FOUND error because route POST /article/:id does not exist (it's DELETE /article/:id).
Note: Your DELETE-query is vulnerable for SQL-injection attacks escaping-query-values
Escape query values:
con.query('DELETE FROM posts WHERE posts.id = ?', [req.params.id]);
Note: Actually, correct http status for this case is 405 METHOD NOT ALLOWED, but express by default doesn't distinguish those cases
app.delete expects to recieve a DELETE request.
xmlhttp.open("POST", page, true); is sending a POST request.
Change the second argument to "DELETE" to make a DELETE request.
you have a delete route in your server, so if you want to send a request to that route, you should pass "DELETE" parameter to xmlhttp.
so simply change
xmlhttp.open("POST", page, true);
to
xmlhttp.open("DELETE", page, true);
also, this answer may help you understand using XMLHttpRequest better
Do not insert params directly into your database query
As others said, you are vulnerable to SQLInjection attacks. you should evaluate params first instead of just inserting it directly into your SQL query
I am new to web development and cannot figure out how to send data from the Node server to the client while also serving an HTML page. I know that res.send() sends the data but I cannot use that without also changing the client display. Here is some code of what I'm trying to do (but does not work)
Server:
app.get('/home', function (req, res) {
res.send("String with info I want in HTML");
res.sendFile(__dirname + '/home.html');
});
Client:
<script>
var xhttp = new XMLHttpRequest();
alert(xhttp.responseText); //Using alert to check if I received the info I wanted
</script>
I know that res.send() sends the data but I cannot use that without also changing the client display.
You can. You just have to have the client ask for the data in the right way.
If the client side code is asking for a URL to be displayed as a new page then you will change the display. So don't do that. Use XMLHttpRequest.
var xhttp = new XMLHttpRequest();
alert(xhttp.responseText); //Using alert to check if I received the info I wanted
You need to:
Create the XHR object
Ask for a URL
Send the request
Wait for the response
Look at the response
You've skipped over steps 2, 3 and 4!
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "/home");
xhttp.addEventListener("load", function () { alert(this.responseText); });
xhttp.send();
res.render() function does the job!
res.render("your html page" , { variable : "String with info you want to send." })
After a user does something on a page, I use ajax to send some data to my Node.js Express server. That server then does this:
router.post('/', function(req, res){
//user authentication then, inside that callback
res.redirect('/dashboard');
}
dashboard.js then does this:
router.get('/', function(req, res, next) {
console.log("dashboard"); //<--This code is running
res.render('index',{title:"You are logged in"});
}
Now the front end is doing this:
function httpGetAsync(theUrl, callback){
let user = document.getElementById('username').value;
let pass = document.getElementById('password').value;
let data = {
"username": user,
"password": pass
}
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("POST", theUrl, true); // true for asynchronous
xmlHttp.setRequestHeader("Content-Type", "application/json; charset=utf-8");
var dataAsJson = JSON.stringify(data);
xmlHttp.send(dataAsJson);
}
Instead of seeing my nice "You are logged in" page, index.html logs to my browser's console. This is obviously because my onclick listener does this:
onclick='httpGetAsync("/createUser", console.log)'
Instead of console.log (which is obviously the wrong thing here), what should I be calling?
How do I get this res.render('index',{title:"You are logged in"}) in dashboard.js to actually render?
This is a lot like ExpressJS : res.redirect() not working as expected?, but that question does not include the portion that includes their front end code which is where I think the problem lies. And the last comment there reads: "No, never figured it out. I ended up building my app differently, with the login part in a modal, instead of another page... Very frustrating".
As XHR are meant to send and revive response you are receiving html page as response with status 301 or 302, the possible solution is to send the redirect url as response instead
router.post('/', function(req, res){
//user authentication then, inside that callback
res.send('/dashboard');
}
and on receiving this response you can redirect to response url on callback
function redirect(res){
window.location = res;
}
onclick='httpGetAsync("/createUser", redirect)'
I am supposed to call a third party vendor - Cybersource using their silent order post. The problem is that I have an accordion page which has 3 panes, Account creation, Service address and billing (on third pane).
I am trying make an ajax call from [http://mydomain/billing][1] TO [http://cybersource/silentorderpost/pay][1].
In the post parameters I am setting response url = [http://mydomain/billing][1] this is where CS will send the response back.
When the Ajax post goes from my website to CS website, I do not get a callback but the Cybersource post the response back to my website [http://mydomain/billing][1] and this reloads my whole accordion page which I am trying to avoid. I understand that During an Ajax call, the Ajax expects a response on the same domain as "Called webservice", i.e. my Ajax post expects that Cybersource will post the response on something like [http://cybersource/response][1]. However, CS posts or redirects the response to my website and this is probably the reason, I never get my callback. When the response is posted my whole accordion page reloads and this causes all sorts of issues.
My Code:
function myFunction() {
//document.getElementById("myForm1").submit();
var http= new XMLHttpRequest();
var url = "https://testsecureacceptance.cybersource.com/silent/pay";
var params = document.getElementById("queryStr");
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send(params);
//Send the proper header information along with the request
http.onreadystatechange = function() {//IT NEVER COMES BACK TO THIS SECTION
if(http.readyState == 4) {
alert(http.responseText);
console.log("I came back");
}
}
}
</script>
USING JQUERY:
function myFunction() {
//document.getElementById("myForm1").submit();
var http= new XMLHttpRequest();
var url = "https://testsecureacceptance.cybersource.com/silent/pay";
var params = document.getElementById("queryStr");
var jqxhr = $.post( url, function() {
alert( "success" );
})
.done(function() {
alert( "second success" );
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "finished" );
});
// Set another completion function for the request above
jqxhr.always(function() {
alert( "second finished" );
});
}
Any solutions?
var xhr = new XMLHttpRequest();
xhr.open('POST',url,true);
var params = document.getElementById("queryStr");
// you need to call this method:
xhr.send(params);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
//return stuff
} else {
//return stuff
}
}
just like i wrote in my comment, you also need to send your request to the server via xmlhttprequestObject.send() before the readystate can change.
greetings
I found a way out. On my form I added an iframe and now when I get a post response from CS, my page does not reload, instead the response is updated in the iframe.
<form action="https://testsecureacceptance.cybersource.com/silent/pay" method ="post" target="myIframe"> ..... </form>
<iframe src="" name="myIframe"></iframe>
I got the same issue when I integrate cyber source silent post order. I resolved it with form with hidden input fields to create the signature and invisible iframe as the target for my form.
Few things you need to take care while integrating cyber source silent post
1. Make sure you are passing all required fields
2.Generate unique application number and uuid otherwise cyber source will consider it as duplicate request
3.create the signature to make sure input fields are not tampered
4.Dont use ajax to submit the request, in this case the call might ge success but cyber source will not call your customer post back URL that you configured for response.