CSS loads but doesn't do anything - html

I'm trying to make a basic multiplayer game with Socket.IO, p5.js and NodeJS, hosting it on Replit.
I have a basic httpServer with socket.io, and it serves the HTML, CSS and JavaScript files fine. But when I put the <link> tag in the HTML to load the CSS, the CSS loads fine (I can see it in the Sources tab in the Chrome DevTools) but it doesn't actually apply to the HTML.
The code is here, but I'll put it here as well.
index.js The main NodeJS file
const { readFileSync } = require('fs');
const { createServer } = require('http');
const { Server } = require('socket.io');
const httpServer = createServer((req, res) => {
const r = /^\/?(index\.(html|css|js))?$/i;
if (!r.test(req.url))
{
res.writeHead(404);
res.end('Not found');
return;
}
const m = req.url.match(r);
// reload the file every time
const content = readFileSync(__dirname + '/public/' + (m[1] || 'index.html'));
const length = Buffer.byteLength(content);
res.writeHead(200, {
'Content-Type': 'text/html',
'Content-Length': length,
});
res.end(content);
});
const io = new Server(httpServer, {
// Socket.IO options
});
let players = {};
io.on('connection', (socket) => {
players[socket.id] = {
id: socket.id,
x: 0,
y: 0
};
socket.on('disconnect', (reason) => {
delete players[socket.id];
});
});
io.on('data', data => {
players[data.id].x += data.x;
players[data.id].y += data.y;
});
setInterval(() => {
io.sockets.emit('data', players);
}, 1000 / 60);
httpServer.listen(6001);
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Multiplayer Online IO Game 2</title>
<link rel="stylesheet" href="index.css">
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js" integrity="sha512-N4kV7GkNv7QR7RX9YF/olywyIgIwNvfEe2nZtfyj73HdjCUkAfOBDbcuJ/cTaN04JKRnw1YG1wnUyNKMsNgg3g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="/index.js" defer></script>
</head>
<body>
</body>
</html>
public/index.css
body
{
margin: 0px;
overflow: hidden;
}
canvas
{
display: none;
}
The canvas' display: none was to see if the CSS actually did anything, but it doesn't.
public/index.js The client JavaScript
let ID = null;
let players = {};
const socket = io({
// Socket.IO options
});
socket.on('connect', () => {
ID = socket.id;
});
socket.on('connect_error', (err) => {
alert(`There was an error connecting to the WebSocket server:\n${err.message}`);
});
socket.on('data', (data) => {
players = data;
});
function setup()
{
createCanvas(windowWidth, windowHeight);
}
function draw()
{
background(255);
fill(0);
for (const id of Object.keys(players))
{
const player = players[id];
circle(player.x, player.y, 10);
}
}

Your server is using the content type text/html for all responses regardless of the type of file being returned. Some web browsers are strict about content-types and will not process a stylesheet if it has the wrong content type. Here's a example fix:
const httpServer = createServer((req, res) => {
const r = /^\/?(index\.(html|css|js))?$/i;
if (!r.test(req.url))
{
res.writeHead(404);
res.end('Not found');
return;
}
const m = req.url.match(r);
// reload the file every time
const content = readFileSync(__dirname + '/public/' + (m[1] || 'index.html'));
const length = Buffer.byteLength(content);
res.writeHead(200, {
// Determine the content type based on the file extension
'Content-Type': m[2] ? getContentType(m[2]) : 'text/html',
'Content-Length': length,
});
res.end(content);
});
function getContentType(ext) {
switch (ext.toLowerCase()) {
case 'html':
return 'text/html';
case 'css':
return 'text/css';
case 'js':
return 'text/javascript';
default:
return 'application/octet-stream';
}
}
You might want to consider using a more full-featured HTTP server such as express instead of rolling your own.

Related

Problems working with new AggregatedView, I need an usage example of this class

I'm trying to load 3 different models in the viewer, and later access the properties in each model, for selecting parts...
The viewer is always looking to the first loaded model, I need to change this. Reading about this I discovered the new AggregatedView class.
Following the documentation I got this:
var view = new Autodesk.Viewing.AggregatedView();
const bubbleNodes = [];
function loadModels(docs) {
const options = {
env: 'AutodeskProduction',
getAccessToken: getForgeToken
};
// Initialize and load a document.
Autodesk.Viewing.Initializer(options, function onInitialized() {
// Get the Viewer DIV
var htmlDiv = document.getElementById('forgeViewer');
// Initialize the AggregatedView view
view.init(htmlDiv, options).then(function () {
console.log(docs)
for (let i = 0; i < docs.length; i++) {
Autodesk.Viewing.Document.load(docs[i], (doc) => {
// Set the nodes from the doc
var nodes = doc.getRoot().search({ type: 'geometry' });
bubbleNodes.push(nodes[0]);
}, (errorCode, errorMsg, messages) => {
// Do something with the failed document.
// ...
console.log(errorCode, errorMsg, messages)
});
}
view.setNodes(bubbleNodes);
});
});
}
I'm always getting this in the error callback --> 5 'Error: 404 (Not Found)' 404
I don`t know what I'm doing wrong.
The Autodesk.Viewing.Document.load is an async task, you cannot use it as you posted above. So, here you go:
<!DOCTYPE html>
<html>
<head>
<title>Multiple 3D Viewer - Autodesk Forge AggregatedView</title>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<!-- The Viewer CSS -->
<link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" type="text/css">
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="viewer"></div>
<!-- The Viewer JS -->
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.js"></script>
<!-- Developer JS -->
<script>
function fetchForgeToken( callback ) {
fetch( 'https://127.0.0.1:8080/api/forge/oauth/token', {
method: 'get',
headers: new Headers({ 'Content-Type': 'application/json' })
})
.then( ( response ) => {
if( response.status === 200 ) {
return response.json();
} else {
return Promise.reject(
new Error( `Failed to fetch token from server (status: ${response.status}, message: ${response.statusText})` )
);
}
})
.then( ( data ) => {
if( !data ) return Promise.reject( new Error( 'Empty token response' ) );
callback( data.access_token, data.expires_in );
})
.catch( ( error ) => console.error( error ) );
}
function launchViewer( models ) {
if( !models || models.length <= 0 )
return console.error( 'Empty model input' );
const options = {
env: 'AutodeskProduction',
getAccessToken: fetchForgeToken
};
const options3d = {
viewerConfig: {
disableBimWalkInfoIcon: true
}
};
function loadManifest( documentId ) {
return new Promise(( resolve, reject ) => {
const onDocumentLoadSuccess = ( doc ) => {
doc.downloadAecModelData(() => resolve(doc));
};
Autodesk.Viewing.Document.load( documentId, onDocumentLoadSuccess, reject );
});
}
Autodesk.Viewing.Initializer( options, function() {
//get the viewer div
const viewerDiv = document.getElementById( 'viewer' );
//initialize the viewer object
const view = new Autodesk.Viewing.AggregatedView();
view.init( viewerDiv, options3d );
const viewer = view.viewer;
const tasks = [];
models.forEach( md => tasks.push( loadManifest( md.urn ) ) );
Promise.all(tasks)
.then( docs => Promise.resolve( docs.map( doc => {
const bubbles = doc.getRoot().search({type:'geometry', role: '3d'});
const bubble = bubbles[0];
if( !bubble ) return null;
return bubble;
})))
.then( bubbles => view.setNodes( bubbles ) );
});
}
const models = [
{ name: 'A.rvt', urn: 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6Zm9yZ2Utb3RnLWxrd2VqN3hwYmdwNjN4NGhsMzM1eTZtMjZvYWtnZ29mL0EucnZ0' },
{ name: 'B.rvt', urn: 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6Zm9yZ2Utb3RnLWxrd2VqN3hwYmdwNjN4NGhsMzM1eTZtMjZvYWtnZ29mL0IucnZ0' },
{ name: 'C.rvt', urn: 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6Zm9yZ2Utb3RnLWxrd2VqN3hwYmdwNjN4NGhsMzM1eTZtMjZvYWtnZ29mL0MucnZ0' },
{ name: 'D.rvt', urn: 'urn:dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6Zm9yZ2Utb3RnLWxrd2VqN3hwYmdwNjN4NGhsMzM1eTZtMjZvYWtnZ29mL0QucnZ0' }
];
launchViewer( models.concat() );
</script>
</body>
</html>
ref: https://gist.github.com/yiskang/c404af571ba4d631b5929c777503891e

Combining Three.js and Node.js to display .obj and .mtl file for a 3d Object in the Website

I want to include three.js (mainly to make a rotatable 3d Sword) into my website Project.
I looked up differnet ways and find it most convinient to use an external tool to create an sword.obj and include this through the THREE.OBJloader.
My first Issue i came accross was that html provided through Node.js couldnt use js. One Option was to use express and the other option( I used ) was to send the js files seperately to the html.
This works perfectly. The main reason i wanted to include this passage, is for the reason that i used the same technique to send my .obj and .mtl file to the html / js in script tags.
My simple Test Server.js is:
const http = require('http');
const fs = require('fs');
const hostname = '127.0.0.1';
const port = 300;
var server = http.createServer(function (request, response) {
console.log(request.url)
if (request.url == '/') {
fs.readFile(__dirname + '/Test/sword.html', function (err, html) {
if (err) {
res.send(500, { error: err });
}
response.writeHeader(200, { "Content-Type": "text/html" });
response.write(html);
response.end();
});
} else if (request.url == '/JS/three.min.js') {
fs.readFile(__dirname + '/JS/three.min.js', function (err, jsFile) {
if (err) {
res.send(500, { error: err });
}
response.writeHeader(200, { "Content-Type": "text/javascript" });
response.write(jsFile);
response.end();
});
}
else if (request.url == '/JS/OBJLoader.js') {
fs.readFile(__dirname + '/JS/OBJLoader.js', function (err, jsFile) {
if (err) {
res.send(500, { error: err });
}
response.writeHeader(200, { "Content-Type": "text/javascript" });
response.write(jsFile);
response.end();
});
}
else if (request.url == '/JS/MTLLoader.js') {
fs.readFile(__dirname + '/JS/MTLLoader.js', function (err, jsFile) {
if (err) {
res.send(500, { error: err });
}
response.writeHeader(200, { 'Content-Length':jsFile.toString().length+'' });
response.write(jsFile);
response.end();
});
}
else if (request.url == '/3D/tent_detailedOpen.obj') {
fs.readFile(__dirname + '/3D/tent_detailedOpen.obj', function (err, jsFile) {
if (err) {
res.send(500, { error: err });
}
response.writeHeader(200, { "Content-Type": "application/object",'Content-Length':jsFile.toString().length+'' });
response.write(jsFile);
response.end();
});
}
else if (request.url == '/3D/tent_detailedOpen.mtl') {
fs.readFile(__dirname + '/3D/tent_detailedOpen.mtl', function (err, jsFile) {
if (err) {
res.send(500, { error: err });
}
response.writeHeader(200, { /* "Content-Type": "text/plain", */'Content-Length':jsFile.toString().length+'' });
response.write(jsFile);
response.end();
});
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
My HTML File (with JS) which shall display the 3d Object:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
</head>
<body>
<div id="Sword">
</div>
<script src="../JS/three.min.js"></script>
<script src="../JS/OBJLoader.js"></script>
<script src="../JS/MTLLoader.js"></script>
<script>
window.onload = function () {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
scene.background = new THREE.Color( 0xffffff );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//THREE.Cache.enabled = true;
const loader = new THREE.OBJLoader();
// load a resource
loader.load(
// resource URL
'../3D/tent_detailedOpen.obj',
// called when resource is loaded
function (object) {
console.log("LOADED");
console.log(object)
scene.add(object);
},
// called when loading is in progresses
function (xhr) {
console.log(xhr.loaded);
console.log(xhr.total);
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
},
// called when loading has errors
function (error) {
console.log('An error happened');
}
);
camera.position.set(2, 2, 2); camera.lookAt(scene.position);
const animate = function () {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
}
</script>
</body>
</html>
This only includes the .obj file which after several hours of trial and error i got to work and to display. But the big Problem is the .mtl file which style the 3d Object.
When i try to include it with following Function (instead of the only obj):
var mesh = null;
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load('../3D/tent_detailedOpen.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load('../3D/tent_detailedOpen.obj', function (object) {
mesh = object;
mesh.position.y = -50;
console.log(mesh)
scene.add(mesh);
});
});
But still there is no 3d, i copied beneath the mesh that is created, but i cant finde the mistake with it. Normally in my understanding it should be displayed.
animations: []
castShadow: false
children: [Gn]
frustumCulled: true
layers: ve {mask: 1}
materialLibraries: ["tent_detailedOpen.mtl"]
matrix: ae {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: ae {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: ""
parent: Ts {uuid: "2D813A87-9F8A-430B-B66F-FE57C67ED03F", name: "", type: "Scene", parent: null, children: Array(1), …}
position: Rt {x: 0, y: -50, z: 0}
quaternion: Lt {_x: 0, _y: 0, _z: 0, _w: 1, _onChangeCallback: ƒ}
receiveShadow: false
renderOrder: 0
rotation: ge {_x: 0, _y: 0, _z: 0, _order: "XYZ", _onChangeCallback: ƒ}
scale: Rt {x: 1, y: 1, z: 1}
type: "Group"
up: Rt {x: 0, y: 1, z: 0}
userData: {}
uuid: "44EB2251-B7A3-4432-BCB4-A01D6D26F119"
visible: true
eulerOrder: (...)
id: 11
modelViewMatrix: ae {elements: Array(16)}
normalMatrix: yt {elements: Array(9)}
useQuaternion: (...)
__proto__: Pe
Does anyone have an Idea why it wont show? I already switched camera position to exclude the posibilty of just the camera not showing it.
Also examples of how to fully implement a 3d object through node.js are a rarity and i couldnt find one.
I would highly appreciate any help and maybe a completly other option how i can create a simple 3d Object(sword) and implement it into my node.js website.
Best Regards
Julian

How to download a file hosted on http webserver in nodejs

I have created a nodejs http webserver to host some files -
var http = require('http'),
fs = require('fs');
var finalhandler = require('finalhandler');
var serveStatic = require('serve-static');
var qs = require('querystring');
var serve = serveStatic("./");
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(req, res) {
var done = finalhandler(req, res);
serve(req, res, done);
if(req.method === "POST") {
if (req.url === "/downloadInstaller") {
var requestBody = '';
req.on('data', function(data) {
requestBody += data;
if(requestBody.length > 1e7) {
res.writeHead(413, 'Request Entity Too Large', {'Content-Type': 'text/html'});
res.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
}
});
req.on('end', function() {
fs1.readFile("./FileToDownload.zip", function(err, data)
{ res.statusCode = 200;
res.setHeader('Content-type', 'text/plain' );
res.write(data);
return res.end();
});
});
}
}
}).listen(8000);
});
Its working good . I can download a file when I hit url - http://localhost:8000/fileToDownload.extension
Now , my index.html looks like -
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<form action="/downloadInstaller" method="post">
<label>OS Flavor : </Label>
<input type="text" id="os" name="os"/>
<input type="submit"/>
</form>
I want to download same file when I will click on submit button.I have written the code for same. But it renders the file in browser instead of downloading it.
How Can i achieve it in nodejs?
Considerably new in nodejs.
Thanks
You should remove this :
res.setHeader('Content-type', 'text/plain' );
And replace it with headers hinting the browser that it should download the file:
res.setHeader('Content-Description', 'File Transfer');
res.setHeader('Content-Type', 'application/octet-stream');
res.setHeader('Content-Type', 'application/force-download'); // only if really needed
res.setHeader('Content-Disposition', 'attachment; filename=FileToDownload.zip');
NB: the "force-download" header is a dirty hack, try without it first.

Getting html form data using http

I need to get data from simple html form (code below) and send it to API (http://netology.tomilomark.ru/doc/#api-ND) that makes hash out of it.
Here is html form code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Form</title>
</head>
<body>
<form action="/sendForm">
Name:<br>
<input type="text" name="firstName" value="">
<br>
Surname:<br>
<input type="text" name="lastName" value="">
<br><br>
<input type="submit" value="Send">
</form>
</body>
And that's what I´ve got on the server side:
"use strict";
const http = require("http");
const fs = require("fs");
const PORT = 3000;
let resObject = {};
let hash;
// Code that sends name + surname to the API and creates hash
// ------------- begin -------------
let options = {
hostname: "netology.tomilomark.ru",
path: "/api/v1/hash",
method: "POST",
headers: {
"firstName": "Evgeny",
"Content-Type": "application/json"
}
};
let req = http.request(options, (res) => {
let resString = "";
res.on("data", (data) => {
resString += data;
});
res.on("end", () => {
console.log(resString);
hash = resString["hash"];
})
});
let reqMessage = JSON.stringify({"lastName": "Kobzev"});
req.write(reqMessage);
req.end();
resObject.firstName = "Evgeny";
resObject.lastName = "Kobzev";
console.log(JSON.stringify(resObject));
// -------------- end --------------
// Create web server that loads the html file
// ------------- begin -------------
const server = http.createServer((req, res) => {
fs.readFile("./logs/form.html", (err, file) => {
res.writeHead(200, {'Content-Type': 'text/html','Content-Length':file.length});
res.write(file);
});
});
server.on("error", (err) => console.error(err));
server.on("listening", () => console.log(`Start HTTP on port ${PORT}`));
server.listen(PORT);
// -------------- end --------------
How can I get data from that simple form and later send it to API? The problem is that I need to use a low level abstraction solution: http and maybe querystring.
Any help will be appreciated!
After working for few minutes I get the code.Here in my code I am printing hash values in terminal.And here is my code
var qs = require('querystring');
var request=require('request');
var util=require('util');
const http= require("http");
const fs= require("fs");
var hash=require('object-hash');
const server = http.createServer((req, res) => {
if (req.url === '/sendForm' && req.method === 'POST') {
var body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
var post= qs.parse(body);
var Fs=hash({NAME:post.firstName});
var Sn=hash({SURNAME:post.surName});
console.log("FirstName:"+post.firstName);
console.log("SurName:"+post.surName)
console.log("Hashed Value Of FirstName:"+Fs);
console.log("Hashed Value Of SurName:"+Sn);
res.end("successfully submitted");
});
}
fs.readFile("./sample.html", (err, file) => {
res.writeHead(200, {'content-type': 'text/html','Content-Length':file.length});
res.end(file);
});
}).listen(3000,function(){
console.log("Server Listening on 3000");
});
Hope this helps for you...

How to read image from HTML file with NodeJS?

I want to read an HTML file.
My HTML content:
<html>
<hear>
<title>Learn NodeJS</title>
</head>
<body>
<center>
<h1>Learn NodeJS with Khuong Pham</h1>
<img width="400" src="/nodejs.png" />
</center>
</body>
</html>
I've tried:
const http = require('http')
const fs = require('fs')
const express = require('express')
const app = express()
const folderPath = __dirname + '/public_files'
app.use(express.static(folderPath))
http.createServer(function(request, response) {
var filePath = folderPath + '/index.html'
console.log(filePath)
fs.access(filePath, fs.F_OK | fs.R_OK, function(err) {
if (err) {
response.writeHead(404, { 'Content-Type' : 'text/html' })
response.end('<h1>File not found</h1>')
} else {
fs.readFile(filePath, function(err, contentFile){
if (!err) {
response.writeHead(200, { 'Content-Type' : 'text/html' })
response.end(contentFile)
} else {
response.writeHead(500, { 'Content-Type' : 'text/html' })
response.end('<h1>Can not read this content</h1>')
}
})
}
})
}).listen(3500)
But when I access http://localhost:3500/, it says:
You are mixing two methods here. Firstly you are trying to use express, but later you are starting your own server using http.createServer Instead you should use express to do so.
Your js should be something similar to below. Have not tested below code. Edit it approiately. This is just to show the idea.
const http = require('http')
const fs = require('fs')
const express = require('express')
const app = express()
const folderPath = __dirname + '/public_files'
//mount your static paths
// renders your image and index.html
app.use(express.static(folderPath))
// renders your index.html
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
//mount your other paths
// in this case render 404.
app.get("*",function (req, res) {
res.status(404).send(''<h1>File not found</h1>'');
});
//start the server.
app.listen(3500, function () {
console.log('Example app listening on port 3500!');
});