Express GET request not reloading page - javascript

I'm trying to send the client the next HTML page (create.html) as a response to a GET request (fired by button) using fetch. I am purposely trying to avoid using a form due to formatting issues and potential future scaling issues. The code registers that the request is sent, received, and is responded to with the file but it simply does not reload the page with it. *res.redirect does also not work. I've attached my code bellow.
JavaScript:
app.get('/', function(req, res) {
console.log(`[00]: Get request recieved at '/'`);
res.sendFile('public/start.html' , { root : __dirname});
})
app.get('/login', function(req, res) {
console.log(`[01]: Get request recieved at '/login'`);
res.sendFile('public/login.html' , { root : __dirname});
})
app.get('/create', function(req, res) {
console.log(`[02]: Get request recieved at '/create'`);
res.sendFile('public/create.html' , { root : __dirname});
})
HTML:
<html>
<head>
<meta charset="utf-8">
<title>HOME PAGE</title>
</head>
<body>
<h1 id='title'>Welcome User!</h1>
<h2>Select an option bellow!</h2>
<button id="btnToLogin">Login</button>
<button id="btnToCreate">Create Account</button>
<p>-ADMIN PANEL-</p>
<button id="btnDisplay">Display Database</button>
<button id="btnTruncate">Truncate Database</button>
<p id='displayText' >[displayText]: Nothing seems to be here...</p>
<script src="start.js"></script>
</body>
</html>
HTML JavaScript:
// Gets elements from start.html
var btnToLogin = document.getElementById('btnToLogin');
var btnToCreate = document.getElementById('btnToCreate');
var btnDisplay = document.getElementById('btnDisplay');
var btnTruncate = document.getElementById('btnTruncate');
var displayText = document.getElementById('displayText');
btnToLogin.addEventListener('click', function() { fetch('/login', { method: 'GET' }) });
btnToCreate.addEventListener('click', function() { fetch('/create', { method: 'GET'}) });
I've cut out most of my code, just unnecessary for the problem I believe. Everything is required properly and server is set up. And incase it matters i've attached a picture of the file structure. Thanks.
File Structure

Fetch performs and gets the data in background. res.redirect redirects a request. And you are sending the request via fetch. Not address bar. In order to do that, you need to use location.href instead of fetch
btnToLogin.addEventListener('click', function() { location.href = '/login' });
btnToCreate.addEventListener('click', function() { location.href = '/create' });

Related

Why is `res.sendFile` not doing anything? No errors, but nothing happens

For some reason res.sendFile in a post method isnt working at all. Like there is no error, but it isnt working. Let me show you the code
app.post('/login',(req, res) => {
var password = req.body.password;
//console.log(password) <- it logs it correctly
if(password == 'hey'){
res.sendFile(path.resolve(__dirname, 'public/index2.html');
res.end('yes')
}else{
res.end('no');
}
});
I also tried changing the path.resolve for path.join and it's doing literally nothing. I added a console.log('hey') and it actually logs that. But it doesnt load the file html.
<script>
$(document).ready(function(){
var pass;
$('#submit').click(function(){
pass=$('#password').val();
$.post("https://heresmypage.repl.co/login",{password: pass}, function(data){
if(data === 'no'){
alert("Password is not correct.");
}
});
})
})
</script>
<input placeholder="Password" id="password">
<input type="submit" value="Submit" id="submit"></button>
Answers will be much appreciated
I can see a few possible reasons:
You're ending the response before it has a chance to send the file by calling end().
When you use sendFile(), you don't call end; it does it for you. (This is true of most of the Response methods that send information — send, json, etc.)
From the end documentation:
Ends the response process. This method actually comes from Node core, specifically the response.end() method of http.ServerResponse.
Use to quickly end the response without any data. If you need to respond with data, instead use methods such as res.send() and res.json().
(my emphasis on "instead")
There's a syntax error in the quoted code: You're missing a ) on the sendFile call. That makes me think this isn't the code you're actually running (since you'd get an error), so perhaps the sendFile call isn't in the code you're actually running.
It may be sending the file, but the browser may be blocking access to it because of the Same Origin Policy if the page you're running that code on isn't from https://heresmypage.repl.co.
If I fix #1 and #2 and ensure that #3 doesn't apply, it works just fine; see *** comments:
index.js:
const express = require("express");
const path = require("path");
const app = express();
app.use(express.urlencoded());
app.post('/login',(req, res) => {
var password = req.body.password;
//console.log(password) <- it logs it correctly
if(password == 'hey'){
res.sendFile(path.resolve(__dirname, 'public/index2.html'));
// *** Added ) −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^
// *** Removed call to `res.end('yes');` here
}else{
res.end('no');
}
});
app.get("/", (req, res) => {
res.sendFile(path.resolve(__dirname, "public/index.html"));
});
app.listen(3000);
public/index.html:
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<title>sendFile Question</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<style>
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
var pass;
$('#submit').click(function () {
pass = $('#password').val();
$.post("/login", { password: pass }, function (data) {
// ^^^^^^^^−−−−−− removed the hardcoded path so the request is relative, to ensure
// the SOP isn't the issue
console.log(data);
if (data === 'no') {
alert("Password is not correct.");
}
});
})
})
</script>
<input placeholder="Password" id="password">
<input type="submit" value="Submit" id="submit"></button>
</body>
</html>
public/index2.html:
<p>Hi</p>
Using the password hey gets me the contents of index2.html in data.

Process form submit response from express server with javascript

(Please correct my terminology if it's not correct.)
My files server.js, run.js and index.html, are in the same directory.
server.js
Sets up the server.
const express = require('express');
const path = require('path');
const run = require('./run.js');
var app = express();
app.get('/index.html', function(req, res){
res.sendFile(path.join(__dirname + '/index.html'));
});
app.get('/', function(req, res){
res.redirect('index.html');
});
app.post('/run', async function(req, res){
var data = await run.run();
res.json(data);
});
app.listen(5000, function () {
console.log('Dev app listening on port 5000');
});
run.js
Will contain functions that consumes time. Here just one function as example:
async function run(){
//do time consuming stuff
var data = {
"status" : "ok",
"a1" : 1,
"a2" : 2
};
return data;
}
module.exports = {
run:run
}
index.html
Simple form.
<!DOCTYPE html>
<html>
<body>
<form id="search-form" action="/run" method="post">
Input:<br>
<input type="text" name="input1" id="input1" value = ""> <br>
<input type="submit" value = "Run">
</form>
<script></script>
<div id="data"></div>
</body>
</html>
When I run the server, go to localhost:5000 in the browser, and click the run button, I get redirected to a page just showing the content of data.
What I would like to happen when I click the the run button is;
The server process /run post request
A response is sent with res.json or res.send to the client
A javascript script on the client side should catch the response, process it, and make some change to the html code (in my case, create some table).
How can I achieve this?
So your problem is that you're using a form. Forms will redirect you to the specified web page with all of the form's data.
You need an XMLHttpRequest.
var xhr = new XMLHttpRequest();
xhr.open("POST", "/run", true);
xhr.send();
If you ever need the data of your form to be submitted as well, I have some documentation on how to do that.
Hope this helps!

Send new HTML page and make GET request to it after POST request from original page

I'm new to Node.js and JavaScript. I have a specific problem but mostly need advice on the best solution.
I'm running a Node server. I want the client to be able to submit a string to the server, then the server to display a new HTML page that shows the string data.
I'm using Express and Socket.io.
In the following files, the client sees index.html, then after submitting the form it sees return.html. I print the input string to the console, and the output is as expected (whatever the user enters). But the return.html is never updated with the input string.
I also tried sending the return.html page and the change_result call in an async series, but the sendFile function never ends and the second function in the series is never called. In previous attempts it worked intermittently with a setTimeout around the emit('change_result') function.
Why doesn't the call to change_result do anything? I used the same technique to update the headings of the original index.html in previous versions. Should I be routing to localhost.../return.html and sending the post data there, or something like that?
server.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var bodyParser = require('body-parser') //for POST request
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
server.listen(8080, function() {
console.log("Server running on port 8080.");
});
var dir = __dirname;
app.get('/', function(req, res) {
res.sendFile(dir + '/index.html');
});
app.post('/', function(req, res) {
var query1=req.body.input1
console.log("Server: In post request.")
console.log(query1);
res.sendFile(dir + '/return.html');
io.emit('change_result', {
result: query1
});
});
index.html
<!DOCTYPE html>
<html>
<body id="body">
<form method="post" action="http://localhost:8080">
String: <input type="text" name="input1" id="input1" />
<input type="submit" id="button1" value="Submit" />
</form>
</body>
</html>
return.html
<!DOCTYPE html>
<html>
<body id="body">
<p id="heading1">Result: </p>
<script>
document.addEventListener('DOMContentLoaded', function() {
var socket = io();
socket.on('change_result', function(data) {
document.getElementById('heading1').innerHTML = "Result: \""+data.result"\"";
});
});
</script>
</body>
</html>
I'm not knee-deep inside socket.io, but IMO the problem is, that the server has no way to know if any listeners are ready.
I think you should emit a 'ready' event, once the return.html is loaded, then listen to 'change_result'. Also separate the socket communication from the POST response on the server. Like so.
server.js
var query;
app.get('/', function(req, res) {
res.sendFile(dir + '/index.html');
});
app.post('/', function(req, res) {
query = req.body.input1;
console.log("Server: In post request.");
console.log(query);
res.sendFile(dir + '/return.html');
});
io.on('connection', function(socket) {
socket.on('ready', function() {
socket.emit('change_result', {result: query});
});
});
return.html
<script>
document.addEventListener('DOMContentLoaded', function() {
var socket = io();
socket.emit('ready', function(data) {});
socket.on('change_result', function(data) {
document.getElementById('heading1').innerHTML = "Result: \""+data.result + "\"";
});
});
</script>

Twilio call button and user input

so I've created this application that allows me to call a phone number from my Twilio account through localhost. I just have to put a / after the port # and the phone number I want to call(localhost:2222/7786453738) and it will send out a call. but I want the user to be able to make that call by inputting a phone number on to the webpage then clicking a button. is that possible? here's my code so far in the index.js file. I run it by going node index.js in the command terminal.
const express = require("express");
const app = express();
const port = 2222;
app.get("/", function(req, resp){
resp.end("welcome to my app");
});
app.get("/:data", function(req, resp){
var accountSid = 'accountSid'
var authToken = 'authtoken'
var client = require('twilio')(accountSid, authToken);
client.calls.create({
url: 'https://demo.twilio.com/welcome/voice/',
to: req.params.data,
from: '6043302056',
}, function(err, call) {
if(err) {
console.log(err);
} else {
console.log(call.sid);
}
})
console.log(req.params.data);
if(req.params.data == "me"){
resp.end("hi raj");
//resp.sendFile(__dirname+"/public/index.html)
} else {
resp.end("Now calling: "+req.params.data);
}
});
app.listen(port, function(err){
if(err){
console.log("error starting "+err);
return false;
}
console.log("port is running. "+port);
})
Twilio developer evangelist here.
You're most of the way there with what you want to achieve. You can absolutely create a form that will take an input from a user and dial the number they enter.
First up, You will want to update your route as the number you send through a form won't be a part of the path, instead it will come as part of the body of the request. In order to read request bodies in express, you will want the body-parser module. So, install that in your project with:
npm install body-parser --save
Then include it in your file and use it with your app:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
Now, form's usually POST their data, rather than working over GET, so let's update your route to receive that POST request and extract the number from the request:
app.post("/calls", function(req, resp) {
const accountSid = 'accountSid'
const authToken = 'authtoken'
const client = require('twilio')(accountSid, authToken);
const number = req.body.number;
client.calls.create({
url: 'https://demo.twilio.com/welcome/voice/',
to: number,
from: '6043302056',
}, function(err, call) {
if(err) {
console.error(err);
} else {
console.log(call.sid);
}
})
console.log(number);
if(req.params.data == "me"){
resp.end("hi raj");
//resp.sendFile(__dirname+"/public/index.html)
} else {
resp.end("Now calling: " + number);
}
});
Now, you need an HTML file that will include a form to make the request to this endpoint. Create an HTML file called index.html and place it in a new folder in your application called public.
You can load static files from the public directory in express with this line, add it near the top, after you create the app:
const path = require('path');
app.use('/static', express.static(path.join(__dirname, 'public')));
Finally we just need the HTML. This is the simplest HTML I could write that would do what you need:
<!DOCTYPE html>
<html>
<head>
<title>Make a call</title>
</head>
<body>
<form action="/" method="POST">
<label for="number">What number do you want to call?</label>
<input id="number" type="tel" />
<button type="submit">Make call</button>
</form>
</body>
</html>
As you can see it is just a form with a single input, the number, and a button to submit it.
Give this all a go and let me know how you get on.
Yes,
first: you can do that, but you need to write the code in HTML File or at least include this code in html file, and call the Twilo's function after you click on the respective button. For that first, render a HTML page, after user enters the address, on that HTML Page give input number and call now button feature. and after user clicks on the button, do:
function callNow() {
var num = document.getElementById('number').value;
client.calls.create({
url: 'https://demo.twilio.com/welcome/voice/',
to: num,
from: '6043302056',
}, function(err, call) {
if(err) {
console.log(err);
} else {
console.log(call.sid);
}
{
Your HTML Code should be:
<input id="number">
<button onclick="callNow()">Call Now</button>
You can include twilio cdn and use this feature. I am just giving you the concept, I hope you will find this helpful.

display a message before (or after) a redirect javascript

I'm trying to display a message after or before a redirect. I looked around the site but I found only jquery and php but I can only use the normal java language. In particular I'm trying to use a div that could be good for me. The problem is that the redirect is on the server side (so I cannot call a javascript function or I cannot put a document.getElementByID). Can you help me? Here is my code:
var express = require('express');
var router = express.Router();
var middleware = require('../middleware');
var mongoose = require('mongoose');
var ObjectId = mongoose.Types.ObjectId;
var User = mongoose.model('User');
var config = require("../../config");
var session;
router.all('/', middleware.supportedMethods('GET, POST'));
router.get('/', function(req, res, next) {
res.render('login');
});
router.post('/', function (req, res) {
var post = req.body;
var query = User.where({userName : post.username});
query.findOne(function(err, user){
if (err) { return err}
if (user) {
user.isValidPassword(post.password, function(n, isMatch){
if(isMatch) {
req.session.user_id = user._id;
res.redirect('/library?' + user._id);
} else{
res.redirect('/login');
}
});
}else{
res.redirect('/login');
}
});
});
module.exports = router;
I would put my message on the res.redirect('/login') (both of them) with two different message. I don't know if I have to create a new page, identical, with a div message or I could find a better solution...
I'm trying to display a message after or before a redirect...The problem is that the redirect is on the server side (so I cannot call a javascript function or I cannot put a document.getElementByID).
Exactly. So you can't do that. Instead, you need to return a redirect to a page with your message on it, and then have that page continue on (after a period of time, or after a user action) to the ultimate destination (/login or whatever).
A minimal intermediary page might look like this:
<!doctype html>
<html>
<head>
<title>Some Relevant Title</title>
<meta charset="utf-8"></meta><!-- Or whatever is appropriate -->
<meta http-equiv="refresh" content="15; url=/login">
</head>
<body>
Message goes here. With the refresh above, the page will refresh after 15 seconds.
</body>
</html>

Categories