Call Node.js APIs from standalone HTML file uisng AJAX - javascript

I have created several Node.JS APIs and tested all APIs using Chrome API Tester. But when I call that API from HTML file using AJAX it doesn't work.
Here is example API to login user.
app.post('/loginuser', async (req, res) => {
var query = 'select id,user_pw from t_user where id=?'
rows = await selectQuery(query, [req.query.id])
res.status(200).send({'result': rows})
});
When I call this API from API tester with user_id and password I can get the parameters from req.query.user_id and req.query.password. But when I call that same API from HTML file, req.query is empty.
Call from API tester:
http://localhost:8081/loginuser?id=userid001&pw=123
Call From HTML file using Ajax:
<script type="text/javascript">
$('#btnSubmit').click(function(){
var email = $('#txtEmail').val()
var password = $('#txtPassword').val()
if(email == "" || password == ""){
alert("Please Enter Id and Password")
return
}
url = "http://localhost:8081/loginuser"
$.ajax({
data: {
id: email,
pw: password,
},
dataType: 'json',
type: 'POST',
url: url
}).done(function(data){
console.log(data)
});
});
</script>

Sending credentials via URL query parameters is generally a very bad idea.
Your Express app should read parameters from the request body...
app.post('/loginuser', async (req, res) => {
const query = "select id, user_pw from t_user where id = ?";
try {
const result = await selectQuery(query, [req.body.id]);
res.json({ result });
} catch (err) {
console.error("/loginuser", err);
res.status(500).send("DB error");
}
});
Make sure it can handle either urlencoded data (that's what jQuery will send), JSON or both
app.use(express.urlencoded()); // handle application/x-www-form-urlencoded
app.use(express.json()); // handle application/json
If you absolutely must send URL query parameters, you need to encode them into the URL jQuery uses
// only adding `id` since you're not using `pw` anyway
const params = new URLSearchParams({ id: email });
$.ajax({
url: `http://localhost:8081/loginuser?${params}`,
method: "post",
dataType: "json"
}).done(console.log);

Related

nodeJs basic authentication issue

I'm getting no proper response while make an API request to external API using basic authentication (username and password) in nodejs (javascript)
I used the below code and the response is "undefined", not sure what is missing here.
But I was able to make a request using postman tool without any issues.
const request = require('request')
const user = '*****';
const pass = '*****!';
const url = 'https://servicenow.com/api/table'
var options = {
url: url,
auth: {
username: user,
password: pass
}
};
request.get(options, (err, res, body) => {
if (err) {
return console.log(err);
}
console.log(body.url);
console.log(body.explanation);
});
Response:
undefined
undefined
if your api right with postman you can do like this based on photo
send a request
click on code
select nodejs- Request
copy

Can't get data from client on server-side with Ionic and Express.js

This question might have been ansked before, but i can't seem to find the correct answer for it. I'm working on a Ionic project where i've created another project with Node.js and express.js to handle all my http requests. Both are running on localhost at the moment. When i'm trying to send some data from my client-side to to server-side, the data that i'm getting from the request looks like this when i console.log(req.body):
{ '{"username":"hello#hello.com"}': '' }
I tryed both req.body[username] and so on to get the data, but then it just gets undefined.
My controller for handling the http request looks like this:
$scope.submit = function(){
var username = $scope.username;
console.log($scope.data.username);
$http({
method: 'POST',
url: 'http://localhost:8000/api/users',
data: username,
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Access-Control-Allow-Origin': '*'}
});
Html element
<input type="text" ng-model="data.username" name="name">
Server-side API looks like this:
router.post('/users', function (req, res) {
var username = req.body;
var newUser = new User({
username: username
})
newUser.save(function (err) {
if (err) {
return res.send(500, err);
}
return res.json(200, newUser);
});
});
Server.js bodyparser included
app.use(bodyParser.json());
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
app.use(bodyParser.urlencoded({ extended: true }));
Object have keys and values
{ key: value }
The object on the body is beeing sent in some wrong way since you're sending a object with they key '{"username":"hello#hello.com"}' which has the value ''.
I would recomend fixing how you're posting to your nodejs/express server. But you can get the value by some hacks. Like this.
const body = {'{"username":"hello#hello.com"}': '' }
const keys = Object.keys(body);
const parsed = JSON.parse(keys[0]);
console.log(parsed.username);
https://jsfiddle.net/wejh0fsk/2/
Edit: So what I am doing here is getting all the keys of the object. There's only one key '{"username":"hello#hello.com"}'. Since that key is a string I am parsing it to get a object. Now I have a object
{ username: 'hello#hello.com' }
And finally I'm logging out the username.
The right solution would to fix how your sending your data to the express server.
I don't quite understand your controller. Your ng-model is data.username but then you're putting
var username = $scope.username
Which should be
var username = $scope.data.username // (that's at least what you're binding to in your view)
Also you want to send an object with the post, not just the value
$scope.submit = function(){
var username = $scope.username;
console.log($scope.data.username);
$http({
method: 'POST',
url: 'http://localhost:8000/api/users',
data: { username: username },
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Access-Control-Allow-Origin': '*'}
});
I am not sure on express parsers but I don't know why you're calling the bodyparser twice. The first one should be enough.

res.redirect from an AJAX call

I'm trying to do a redirect after an ajax put request. I plan on using pure JS client side for validation.
Client:
$(document).ready(function() {
login = () => {
var username = $("[name='username']").val()
var password = $("[name='password']").val()
$.ajax({
type: "put",
url: '/login',
data: {
username: username,
password: password
}
// success: function(response) {
// console.log('Success:')
// console.log(response.user)
// Cookies.set('username', response.user.username)
// Cookies.set('first_name', response.user.first_name)
// Cookies.set('last_name', response.user.last_name)
// Cookies.set('email', response.user.email)
// window.location.href = window.location.origin + '/'
// },
// error: function(error) {
// console.log("Error:")
// console.log(error)
// }
})
}
logout = () => {
console.log("Log out clicked.")
Cookies.remove('username')
Cookies.remove('first_name')
Cookies.remove('last_name')
Cookies.remove('email')
window.location.href = window.location.origin + '/logout'
}
})
Server:
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('main')
});
router.put('/login', function(req, res) {
// Password is not encrypted here
console.log('req.body')
console.log(req.body)
User.findOne({ username: req.body.username }, function(err, user) {
// Password is encrypted here
if (err) throw err
console.log('user')
console.log(user)
bcrypt.compare(req.body.password, user.password, function(err, result) {
if (result) {
var token = jwt.encode(user, JWT_SECRET)
// return res.status(200).send({ user: user, token: token })
return res.redirect('/')
} else {
return res.status(401).send({error: "Something is wrong."})
}
})
})
})
I can't get main.hbs to render after a successful login. My commented code works, but I'm trying to do my redirect server side rather than client side because I'm told that it's better for security.
You should know when to use href and replace functionalities.
window.location.replace(...) will best way to represent an HTTP redirect.
Reason
When compared to window.location.href, window.location.replace(...) is better to use in a HTTP redirect scenario because replace() avoids keeping the originating page in the session history, this helps users to avoid get stuck in a never-ending back-button fiasco.
Summary
If you want to illustrate clicking on a link, use location.href
If you want to illustrate an HTTP redirect, use location.replace
Sample
// an HTTP redirect
window.location.replace("http://example.com");
// clicking on a link
window.location.href = "http://example.com";
Update
The server cannot do a redirect from an ajax request. In the end ajax involves the client (browser).
If you want, you can send the instruction of a redirection through the server side call, but it will be end up again on client side, in the callback.
You can do that by returning an object from the server which contains the url you want to redirect to. Then use javascript to change the document's location property. Like Below:
Server Side Code
if (result) {
var token = jwt.encode(user, JWT_SECRET)
return res.status(200).send({result: 'redirect', url:'/'})
} else {
return res.status(401).send({error: "Something is wrong."})
}
And then in Client Side Javascript:
$.ajax({
type: "put",
url: '/login',
data: {
username: username,
password: password
}
success: function(response) {
if (response.result == 'redirect') {
//redirecting to main page from here.
window.location.replace(response.url);
}
}
});
Apart from this your commented code is the correct way to do this. Just like one of the comments in you question "server side redirect is deadend for an ajax request as the instruction is not for the browser but some javascript handler."
I don't think what you want to do is possible. An AJAX request is meant just to pass data back and forth. What happens now is that you need to script client side behavior on your end. This means the AJAX request will pass a 302 and other data that comes along for the ride to the callback on JS. No client side behavior can be altered from the server. It is up to you to do something with the AJAX returned values. If 500, throw an error message, 200 do something etc.
The only way you can get a server redirect to work is by traditional HTML form submission.

Javascript scraper logging in

I seem to be doing something wrong.
I have a student website that I want to scrape, but first I need to log in. Currently I have a python scraper that does it. The website logs in with a post request to a url containing a sid and PIN.
var login_url = 'https://example.com';
var formData = {
sid: 'username',
PIN: 'password'
}
How would I go about creating the same scraper but with javascript? I have seen the request library, which seems like what I want to use but cannot get it to work.
You need to use the request module to POST the form data to your endpoint. The response from the server will be in the call back to the .post() method.
const request = require('request');
// do not reassign "request", if you need to set properties us a different variable
// use the action= value from the form for the URL
const url = 'https://central.carleton.ca/prod/twbkwbis.P_ValLoginn';
const data = {
sid: 'username',
PIN: 'password',
};
request.post({ url: url, formData: data }, (err, response, body) => {
if (err) {
console.log('failed', err);
} else {
console.log('the response', body);
}
});
If you are interesting in parsing the resulting HTML I recommend using CheerioJS - much like jQuery but server side.

How do I transfer data from a client-side form input to a server-side Nodejs script?

I'm trying to implement functionality which takes data from form inputs on the client-side and sends it to the server to be processed by my Nodejs backend.
I've got the server-side function working, but I'm unsure as to how I would go about sending the data from the client-side form to my backend server via the $.ajax GET request that submits the form.
The code I have so far:
Server side function:
app.get('/id', function(req,res) {
var query = "SELECT * FROM Control";
connection.query(query, function() {
console.log(query);
});
});
Client side function:
function select()
{
$.ajax({
type: 'get',
url: '/id',
success: function(data) {
var ceva = data;
console.log('#ceva');
},
error: function(err) {
console.log(err);
}
});
}
You want to use a POST request rather than a GET request. Doing so will allow you to send data along with the request that you can then use in your query on the server side and send the response back to your client. Like so:
Client Side
function select() {
var id = $('#My-ID-Input').val();
$.ajax({
type: 'post',
url: '/id',
data : {
id : id
},
success: function(data) {
var id = data.id;
$('#My-ID-Input').val(id);
},
error: function(err) {
console.log(err);
}
});
}
Server Side
app.post('/id', function(req, res) {
var data = req.body;
var id = data.id;
var query = "SELECT * FROM Control WHERE id=" + id;
connection.query(query, function(error, result) {
console.log(result);
res.send(result);
});
});
GOTCHA!
You need to make sure that you have the express bodyparser
middleware implemented into your server to ensure that the data sent
as the body of the post request is then parsed into an object literal
on the server side. In your server module/file, you'll need to include the following code, and ensure that you've npm install body-parser:
var bodyParser = require('body-parser');
app.use( bodyParser.json() );

Categories