So whats happening is I have a reactjs project that has react router. So when I try and hit /dashboard/stream it's getting the index.html off the server but then the css and js are getting 301 errors and it's not displaying anything.
express server
const express = require('express');
const {
createServer
} = require('http');
const io = require('socket.io');
const haiku = require('./haiku');
const app = express();
const server = createServer(app);
const userIds = {};
const noop = () => {};
app.use('/*', express.static(`${process.cwd()}/../client`));
/**
* Random ID until the ID is not in use
*/
function randomID(callback) {
const id = haiku();
if (id in userIds) setTimeout(() => haiku(callback), 5);
else callback(id);
}
/**
* Send data to friend
*/
function sendTo(to, done, fail) {
const receiver = userIds[to];
if (receiver) {
const next = typeof done === 'function' ? done : noop;
next(receiver);
} else {
const next = typeof fail === 'function' ? fail : noop;
next();
}
}
/**
* Initialize when a connection is made
* #param {SocketIO.Socket} socket
*/
function initSocket(socket) {
let id;
socket
.on('init', () => {
randomID((_id) => {
id = _id;
userIds[id] = socket;
socket.emit('init', {
id
});
});
})
.on('request', (data) => {
sendTo(data.to, to => to.emit('request', {
from: id
}));
})
.on('call', (data) => {
sendTo(
data.to,
to => to.emit('call', { ...data,
from: id
}),
() => socket.emit('failed')
);
})
.on('end', (data) => {
sendTo(data.to, to => to.emit('end'));
})
.on('disconnect', () => {
delete userIds[id];
console.log(id, 'disconnected');
});
return socket;
}
module.exports.run = (config) => {
server.listen(config.PORT);
console.log(`Server is listening at :${config.PORT}`);
io.listen(server, {
log: true
})
.on('connection', initSocket);
};
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<link href="/dist/css/app.min.css" rel="stylesheet">
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="/dist/js/app.min.js"></script>
</body>
</html>
how come my index.html is loaded but then the js and css isnt.
folder structure is this:
server
...
client
dist
css
js
index.html
...
To me I can't see if it's loading that index.html file how it can't load the css and js that are linked to it.
The problem is that you are using absolute path for the static files because they start with a / so if the url is /dashboard/stream then it will tries to load the css and js file from /dashboard/dist/....
To fix it remove the / from the beginning of the path to have a relative path.
<link href="dist/css/app.min.css" rel="stylesheet">
and
<script type="text/javascript" src="dist/js/app.min.js"></script>
This does the trick with Angular so why not with React considering that you are using front-end routing:
Use an absolute path in your server.js file:
app.use('/public', express.static(path.join(__dirname, '../client/dist')));
Serve your front-end routes in your server.js file:
app.get('*', function(req, res, next) {
res.sendFile("../client/index.html", { root: __dirname });
});
Now you should be able to access all the files inside the dist directory.
f.e: <script type="text/javascript" src="./public/js/app.min.js"></script>
Related
I'm new to Node.js and I'm just trying to create simple web server that can serve HTML, JS, and CSS files.
The server works and I can view index.html in localhost. But I can't seem to link the request.js to index.html. Here's my project structure:
--public
----js
------request.js
----index.html
--app.js
app.js
const http = require("http");
const fs = require('fs').promises;
const host = 'localhost';
const port = 8000;
const requestListener = function (req, res) {
fs.readFile(__dirname + "/public/index.html")
.then(contents => {
res.setHeader("Content-Type", "text/html");
res.writeHead(200); // success status code
res.end(contents);
})
.catch(err => {
res.writeHead(500);
res.end(err);
return;
});
};
const server = http.createServer(requestListener);
server.listen(port, host, function(error) {
if (error) {
console.log('Something went wrong', error)
}
else {
console.log(`Server is running on http://${host}:${port}`);
}
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="/js/request.js" defer></script>
<title>Water Web Dev</title>
<body>
</body>
</html>
</head>
request.js
const axios = require('axios');
const getBtn = document.getElementById('get-btn');
const getData = () => {
axios.get('https://reqres.in/api/unknown')
.then(function (response) {
// success
console.log(response);
})
.catch(function (error) {
// error
console.log(error);
})
.then(function () {
// always executed
});
}
getBtn.addEventListener('click', getData)
You should server your css & js files as static files.
I want to be able to write functions in multiple .js files and use the same socket that is create in my main server.js
server.js:
var express = require('express')
var app = express()
var http = require('http')
var server = http.createServer(app)
var io = require('socket.io')(server)
var GOR = require('./gor')
var path = require('path');
app.use(express.static(path.join(__dirname, '/public')));
//handles get request and serves index.html
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/index.html');
});
//wait for server to start
server.listen(8080,()=>{
console.log("server started");
setInterval(emit_data,5000);
emit_data();
//setInterval(GOR.send_from_another_js,5000);
//GOR.send_from_another_js(io);
})
function emit_data(){
io.emit( 'update', "webserver.js");
}
As you can see from the code above, I have a function that emits to socket every 5 seconds and that works fine. I have confirmed it already.
All I want to do now, is to create a seperate.js file and keep all my functions there to make the code look cleaner. I name another .js file gor.js:
gor.js:
//I want to call this function in my webserver.js and transmit this socket
function send_from_another_js(io){
console.log("function called");
io.emit( 'update', "another_js");
}
module.exports = {
send_from_another_js
}
When I call this function in my server.js , it does not work:
server.listen(8080,()=>{
console.log("server started");
setInterval(GOR.send_from_another_js,5000);
GOR.send_from_another_js(io);
})
What is correct way to use the same .io in other .js files? The above does not work.
EDIT1
In my .html, I wait for a message on socket:
window.addEventListener('DOMContentLoaded', () => {
socket.on('update', function(number_to_set) {
console.log("socket update received");
document.getElementById('number1').innerHTML = number_to_set;
});
var button = document.getElementById("operation_code_button");
button.addEventListener("click", function(event){
var val = document.getElementById("operation_code_input").value;
console.log("socket clicked, emmiting data");
socket.emit('button_click',val);
});
})
And in my .js file I emit to this socket every 5 seconds:
server.listen(8080,()=>{
console.log("server started");
setInterval(emit_data,5000);
emit_data();
})
After 5 seconds, I can see that my webpage update data so everything works!!!
I want to declare the emit_data function inside another .js file and use it in my main .js file.
The function in my secondary .js file ( gor.js):
function send_from_another_js_1(io){
io.emit( 'update', data);
}
I want to call it in my main .js the same way I call emit_data
You need to wait for your server to get initialized. You are calling your function before socket.io is ready. That's why io.emit function is 'undefined'.
server.listen(8080,()=>{
GOR.send_from_another_js(io);
})
Edited:(3)
Trust it is what you are looking for...
"server.js"
const content = require('fs').readFileSync(__dirname + '/index.html', 'utf8');
const httpServer = require('http').createServer((req, res) => {
// serve the index.html file
res.setHeader('Content-Type', 'text/html');
res.setHeader('Content-Length', Buffer.byteLength(content));
res.end(content);
});
const io = require('socket.io')(httpServer);
const apple = require("./File2.js")
apple.send_from_another_js_1(io);
apple.send_from_another_js_2(io);
var port = 3000; //wamp server
var prompt = 'Open browser at http://localhost:'
httpServer.listen(port, () => {
console.log(prompt, port);
});
"File2.js"
function send_from_another_js_1(io){
io.on('connection', function (socket) {
socket.on('file2_1_EventTrigged', function (data) {
socket.emit('update1', "send_from_another_js_1(io) : "+ data);
console.log("+++ function send_from_another_js_1(io) called");
});
});
}
function send_from_another_js_2(io){
io.on('connection', function (socket) {
socket.on('file2_2_EventTrigged', function (data) {
socket.emit('update2', "send_from_another_js_2(io) : "+ data);
console.log("... function send_from_another_js_2(io) called");
});
});
}
module.exports = {
send_from_another_js_1,
send_from_another_js_2
}
"index.html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Content-Type" content="text/html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="keywords" content="HTML, CSS, JavaScript">
<meta name="author" content="Dr.Chaiya Tantisukarom">
<meta http-equiv="Cache-Control" content="public, max-age=31536000">
<title>NodeJS socket.io</title>
</head>
<body>
<h1 style="text-align: center;">Hello another world</h1>
<div style="text-align: center;">
<span>
<button onclick="file2_1()">file2_1</button>
</span>
<span>
<button onclick="file2_2()">file2_2</button>
</span>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('connect',()=>{
//alert('Connected');
})
function file2_1(){
socket.emit('file2_1_EventTrigged', "Hello file2_1, how are you today?");
}
socket.on('update1', (data)=>{
alert(data);
})
function file2_2(){
socket.emit('file2_2_EventTrigged', "Hi file2_2, trust you are ok.");
}
socket.on('update2', (data)=>{
alert(data);
})
</script>
</body>
</html>
Cheers !!!
When you call this:
server.listen(8080,()=>{
console.log("server started");
setInterval(GOR.send_from_another_js,5000);
GOR.send_from_another_js(io);
})
setInterval() isn't providing a parameter for GOR.send_from_another_js(), so io becomes undefined.
To fix this, I would use a second lambda expression inside of your setInterval() call.
server.listen(8080, () => {
console.log("server started");
setInterval(() => {
GOR.send_from_another_js(io);
}, 5000);
GOR.send_from_another_js(io);
});
I am working on a project to manage printers with CUPS command-line, I have multiple "api's" that make different thinks, for now i just want so see my parsed JSON result in a view, but I'm clueless on how to pass that value trough Express and then render it in a EJS view:
my api:
const spawnSync = require("child_process").spawnSync;
const parseStdout = require('../utils/utils.js');
function lpstat(){
let printerList = spawnSync("lpstat -p", {
timeout: 10000,
encoding: "utf-8",
});
let parsedList = parseStdout(printerList);
let onlyPrinterList = parsedList.filter(function (line) {
return line.match(line.match(/^printer/) || line.match(/^impressora/));
});
let onlyPrinterNames = onlyPrinterList.map(function (printer) {
return printer.match(/(?: \S+)/)[0].trim();
});
process.on('exit', (code) => {
process.kill();
});
//this is what i want to pass to the view
return JSON.stringify(onlyPrinterNames);
}
my app.js
const express = require('express');
const app = express();
app.listen(3000);
app.set('view engine', 'ejs');
app.get('/lpstat',(req,res) => {
//what should i use here?
res.render('lpstat')
});
my lpstat.ejs
<html lang="en">
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>lpstat</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
<p>lpstat result:</p>
<%= what should i use here?%>
</body>
</html>
The second parameter in res.render defines the data that is given to your templates:
app.get('/lpstat',async (req,res) => {
// Call your api here to fill the variable
const printers = lpstat()
res.render('lpstat', {
printers
})
});
You will be able to use this in your ejs template then
<p>lpstat result:</p>
<%= printers %>
You will need to replace callApi with whatever function is used to fetch your data. I used async/await for a simpler answer, can be done with callbacks as well.
I have a problem with data stubbing in Cypress 6. I am trying to implement the exchange of real data from the server to custom data. I read the docs and came to the conclusion that
describe("test", () => {
it("intercept", () => {
cy.intercept("http://localhost:3000/spoons", (req) => {
req.reply((res) => {
let { body } = res;
body.newProperty = "new";
console.log(res.body);
return body;
});
});
});
});
will be the solution, however... body in networking for request http://localhost:3000/spoons returns to me
{
"sizes": [
"huge",
"small"
],
"colors": [
"yello",
"brown"
],
"build": {
"back": true,
"front": true
}
}
but in the console.log as it shows what res.body has, it gets an empty console.log as if it had nothing res.body in it.
Edit #1
About internal "server" I made just simple express server with a website which make fetch request to have easy another request in "Networking". It was made just as a battlefield to train intercept and other stuff. There is the only endpoint to this /spoons
server.js
const express = require("express");
const app = express();
const port = 3000;
const path = require("path");
const obj = {
sizes: ["huge", "small"],
colors: ["yello", "brown"],
build: {
back: true,
front: true,
},
};
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname + "/index.html"));
});
app.get("/spoons", (req, res) => {
res.json(obj);
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
<script>
console.log(fetch("http://localhost:3000/spoons"));
</script>
</html>
It works for intercepting external network requests,
/// <reference types="#cypress/fiddle" />
const test = {
html: `
<script>
fetch('https://jsonplaceholder.typicode.com/todos/1')
</script>
`,
test: `
cy.intercept('https://jsonplaceholder.typicode.com/todos/1', req => {
req.reply((res) => {
let { body } = res;
body.newProperty = "new";
console.log(res.body);
return body;
});
})
`
}
it('test', () => {
cy.runExample(test)
})
This logs
{
completed: false,
id: 1,
newProperty: "new", // added by intercept
title: "delectus aut autem",
userId: 1
}
Can you explain the api server and client ports in more detail?
I set up your server, and found it works ok.
The only thing I changed was to add a no-store header to the server response (stops browser seeing status code '304').
Without it every second refresh of the Cypress test cy.intercept() did not trigger. That may actually be fixable in the test by adding a full route matcher to cy.intercept() instead of just the url.
app.use((req, res, next) => {
res.set('Cache-Control', 'no-store')
next()
})
app.get("/", (req, res) => {...
I also modified the script in the app to console.log in .then(), otherwise you just get the promise object.
<script>
fetch('http://localhost:3000/spoons')
.then(res => res.json())
.then(res => console.log('app', res))
</script>
This is the spec I used.
it('test', () => {
cy.intercept('http://localhost:3000/spoons', req => {
req.reply((res) => {
let { body } = res;
body.newProperty = "new";
console.log('intercept', res.body);
return body;
});
})
cy.visit('../app/intercept-mod-response-local-server-2.html')
})
Is it possible to "listen" an input text field at nodejs ?
I want to use a search input on my html page and i want to listen "live" any value that user types. Not to take the final value with a submit button and body parser.
I try to add an event listener after select my html input, but my selector is undefined.
here is my server.js file
// 3rd part modules
const express = require('express')
const hbs = require('hbs')
const fs = require('fs')
const moment = require('moment')
// App modules
const userData = require('./fetch')
// App basic configs
const port = process.env.PORT || 3000
const app = express()
//Log when someone is on app
app.use((req, res, next) => {
const now = moment().format("D MMM YYYY, HH:mm")
const clientIp = req.ip
const log = `${now}: from ${clientIp}`
fs.appendFile('server.log', `${log}\n`, (err) => {
if (err) throw err
})
next()
})
// Maintenance mode
// app.use((req, res, next) => {
// res.render('maintenance.hbs', {
// pageTitle: 'Maintenace mode'
// })
// })
// Express middleware to store public files & static pages
app.use(express.static(`${__dirname}/public`))
// View engine Handlebars
app.set('view engine', 'hbs')
// Use partials for header and footer
hbs.registerPartials(`${__dirname}/views/partials`)
// Pass custom functions everywhere
hbs.registerHelper('getCurrentYear', () => {
return new Date().getFullYear()
});
app.get('/', (req, res) => {
res.render('home-page.hbs', {
welcomeMessage: 'Welcome to home page',
pageTitle: 'Home page',
location: userData.location,
currentTemp: userData.currentTemp,
feelTemp: userData.feelTemp
})
})
// Don't forget the command to nodemon to see changes on hbs files
// nodemon server.js -e js,hbs,html,css
app.listen(port, () => {
console.log(`Server is up on ${port}`)
})
Here is my fetch.js file
// 3rd part library
const axios = require('axios')
// Input selection
const locationInput = document.querySelector('#locationInput').value()
// Encode user data & Use it to fetch his location
const encodedAddress = `greece${encodeURIComponent(locationInput)}`
const geocodeUrl = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodedAddress}&key=AIzaSyAnzbpJRrrx9xl2ZjRdwOx4APrn-zgVscM`
const getWeatherData = async (encodedAddress) => {
const location = await axios(geocodeUrl)
if (location.data.status === 'ZERO_RESULTS') {
throw new Error('Unable to find that address.')
}
const lat = location.data.results[0].geometry.location.lat
const long = location.data.results[0].geometry.location.lng
const weatherUrl = `https://api.darksky.net/forecast/95886b065ed14ca53b317610064fe04a/${lat},${long}?units=ca`
const weatherData = await axios.get(weatherUrl)
return {
location,
weatherData
}
}
getWeatherData(encodedAddress).then((info) => {
const location = info.location.data.results[0].formatted_address
const currentTemp = info.weatherData.data.currently.temperature
const feelTemp = info.weatherData.data.currently.apparentTemperature
return {
location,
currentTemp,
feelTemp
}
}).catch((e) => {
if (e.code === 'ENOTFOUND') {
console.log('Unable to connect to API servers')
} else {
console.log(e.message)
}
})
module.exports = {
location,
currentTemp,
feelTemp
}
And here is my html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Home</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
{{> header}}
<p>{{welcomeMessage}}</p>
<p>This is home page</p>
<input id="locationInput" type="text" placeholder="Location">
<p>{{location}}</p>
<p>{{currentTemp}}°C</p>
<p>Feels like {{feelTemp}}°C</p>
{{> footer}}
</body>
</html>
You can use event onchange of that input to send request like ajax or socket.io,etc.
onchange may be is different (onChange in reactjs, .change() method for jquery, ...)