i had my app with http, but i want add https, but i don't know how enable https on socket.io. The problem when i replaced http in 'require('socket.io)(https ....)' socket.io launch 404 error.
const http = require('http').Server(app);
const io = require('socket.io')(http, { pingInterval: 2000, pingTimeout: 7000,});
var https = require('https');
var fs = require('fs');
io.on('connect', socket => {
socket.on('ask', function(msg) {
search
.query(msg, socket.user, socket.token)
.then(result => {
socket.emit('response', result);
})
.catch(err => {
console.log(err);
socket.emit('response', {
msg: { text: "Lo siento, no puedo entender eso " },
type: 'error',
});
});
});
skills.registerClient(socket, socket.user).catch(err => {
console.warn('Failed to register client', err);
});
});
const port = await global.db.getGlobalValue('port');
http.listen(port, () => {
console.log(`Server started on http://localhost:${port}`);
});
const sslPort = '1443';
const server = https.createServer(httpsOptions, app)
.listen(sslPort, () => {
console.log(`Https server on https://localhost:${sslPort}`);
});
I am Currently using this:
const fs = require('fs');
const options = {
rejectUnauthorized: true,
key: fs.readFileSync('<SSL KEY PATH>/privkey.pem'),
cert: fs.readFileSync('<SSL CERT PATH>/fullchain.pem')};
const app = require('https').createServer(options);
const io = require('socket.io')(app);
io.on('connection', socket => {
console.log("New Connection");
socket.on('ask', function(msg) {
//your code here
});
});
app.listen(<PORT>); //e. g. 8080, Integer
First, you need to create cert and key for ssl.
After key and cert are generated, you can code like the following:
const express = require('express')
const https = require('https')
const fs = require('fs')
const port = 8888
const cert = fs.readFileSync('/path/to/your_cert.cert')
const key = fs.readFileSync('/path/to/your_key.key')
const SSLOption = {
key, cert
}
app = express()
let server = https.createServer(SSLOption, app)
server.listen(port, () => {
console.log('server started on port: ' + port)
})
app.get('/', (req, res) => {
res.send('Working good...')
})
const io = require('socket.io')(server)
io.on('connection', (socket) => {
console.log(socket)
})
enter image description here
This is the error.
var httpsOptions = {
key: fs.readFileSync(path.join(__dirname + '/ssl/localhost-key.pem')),
cert: fs.readFileSync(path.join(__dirname + '/ssl/localhost.pem'))
};
This is my httpsOptions.
Related
I am trying to connect a backend layer running on localhost, below is the source code:
const { createServer } = require("http");
const cors = require("cors");
const photos = require("./photos");
const app = require("express")();
const WebSocket = require("ws");
app.use(cors());
app.get("/", (req, res) => {
res.status(200).json({});
});
app.get("/photos", (req, res) => {
res.status(200).json({ photos });
});
const clients = new Set();
app.post("/photos/:id", (req, res) => {
const photo = photos.find((p) => {
return p.id === req.params.id;
});
photo.status= "PENDING";
// Send back an approval
const timeout = (3 + Math.floor(Math.random() * 4)) * 1000;
setTimeout(() => {
photo.status = "APPROVED";
clients.forEach((ws) => {
ws.send(JSON.stringify({ event: "APPROVED", photo }));
});
}, timeout);
res.status(200).json({ photo });
});
const port = process.env.PORT || 3001;
const server = createServer(app);
server.listen(port, () => {
console.log(`Starting server on port ${port}`);
});
const wss = new WebSocket.Server({ path: "/ws", server });
wss.on("connection", (ws) => {
clients.add(ws);
console.log("WebSocket connection established");
ws.on("close", () => {
clients.delete(ws);
console.log("WebSocket connection closed");
});
});
As on react client we can't use "ws" so I tried using both "websocket" package but I am not able to connect to "http" as it is not supported. Below is the source code:
import React from "react";
import { w3cwebsocket as W3CWebSocket } from "websocket";
const client = new W3CWebSocket('http://localhost:3001/ws');
// const client = new W3CWebSocket('ws://localhost:3001');
function App() {
React.useEffect(
() => {
client.onopen = () => {
console.log('WebSocket Client Connected');
};
client.onmessage = (message) => {
console.log(message);
};
}, []
)
return null
}
Need help at client level to connect to 'http://localhost:3001/ws' to establish and listen connection.
You are connecting to the wrong url. In following line on the server, you specify a path as /ws .
const wss = new WebSocket.Server({ path: "/ws", server });
So you need to connect to the specified path.
const client = new W3CWebSocket('ws://localhost:3001/ws');
If you remove the path: "/ws" from your createServer, the url ws://localhost:3001 (notice, no /ws path.. )should also work as expected.
Here's an example which worked on my machine ( without react, it's for showing socket connection.)
Client
var W3CWebSocket = require('websocket').w3cwebsocket;
const client = new W3CWebSocket('ws://localhost:3001/ws');
client.onopen = () => {
console.log('WebSocket Client Connected');
};
client.onmessage = (message) => {
console.log(message);
};
client.onerror = function() {
console.log('Connection Error');
};
Server
const { createServer } = require("http");
const cors = require("cors");
const app = require("express")();
const WebSocket = require("ws");
app.use(cors());
const port = process.env.PORT || 3001;
const server = createServer(app);
server.listen(port, () => {
console.log(`Starting server on port ${port}`);
});
const wss = new WebSocket.Server({ path: "/ws", server });
wss.on("connection", (ws) => {
console.log("WebSocket connection established");
ws.on("close", () => {
console.log("WebSocket connection closed");
});
});
I have 2 scripts in node js. One uses 'http' and other uses 'net'. I want to make these scripts together in one script. My 'http' script are as below:
const http = require('http');
const hostname = 'localhost';
const port = 3000;
const server = http.createServer((req, res) => {
console.log(req.headers);
res.statusCode = 200;
res.end('<html><body><h1>Hello, World!</h1></body></html>');
})
server.listen(port, hostname);
'net' script:
var net = require('net');
var client = new net.Socket();
client.connect(4352, 'x.x.x.x', function() {
console.log('Connected');
client.write('%1POWR 1\r\n');
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
client.on('close', function() {
console.log('Connection closed');
});
My purpose is to run the 'net' script once I start the 'http' script.
Wrap the whole net script in a exported function:
var net = require('net');
module.exports = () => {
var client = new net.Socket();
client.connect(4352, 'x.x.x.x', function() {
console.log('Connected');
client.write('%1POWR 1\r\n');
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
client.on('close', function() {
console.log('Connection closed');
});
}
Import and execute the exported function in http script:
const http = require('http');
const hostname = 'localhost';
const port = 3000;
require('path/to/net/script')() //Add to anywhere you like
const server = http.createServer((req, res) => {
console.log(req.headers);
res.statusCode = 200;
res.end('<html><body><h1>Hello, World!</h1></body></html>');
})
server.listen(port, hostname);
[`const express = require('express');
const app = express();
const https = require('https');
const url = "https://api.thevirustracker.com/free-api?countryTimeline=US";
app.get("/", (req ,res) => {
res.send("Server is Running")
https.get(url, (response) => {
response.on("data", (data) => {
const TimelineData = JSON.parse(data);
console.log(TimelineData);
})
})
})
app.listen(3000, ()=>console.log("Server is Running 0n 5000"));`]1
const express = require('express');
const app = express();
const https = require('https');
const url = "https://api.thevirustracker.com/free-api?countryTimeline=US";
app.get("/", (req ,res) => {
res.send("Server is Running")
https.get(url, (response) => {
response.on("data", (data) => {
const TimelineData = JSON.parse(data);
console.log(TimelineData);
})
})
})
app.listen(3000, ()=>console.log("Server is Running 0n 5000"));
To deliver large data in an effective manner API send data in chunk/stream format. and to receive each chunk it triggers the 'data' event and in your case, it might be possible that API sends data in chunk format. and it will not send you complete data in a single event.
Let's assume the complete response of your API is :
{ name: 'bella', age: 34, count: 40138 }
And API send it in 2 chunks :
Chunk1: { name: 'bella', age: 34, count: 4013
Chunk2: 8 }
In that case Json.Parse() on Chunk1 or Chunk2 will not work and threw an exception.
To deal with this problem you need to listen to the 'end' event and capture data from the'data' and parse it in the 'end' event.
Use the below code:
const express = require('express');
const app = express();
const https = require('https');
const url = "https://archive.org/advancedsearch.php?q=subject:google+sheets&output=json";
app.get("/", (req, res) => {
res.send("Server is Running")
https.get(url, (response) => {
var responseData = '';
response.on("data", (dataChunk) => {
responseData += dataChunk;
})
response.on('end', () => {
const TimelineData = JSON.parse(responseData);
console.log(TimelineData);
});
}).on('error', (e) => {
console.error(e);
});
})
app.listen(5000, () => console.log("Server is Running 0n 5000"));
The "data" event can be fired multiple times: https://nodejs.org/api/http.html#http_class_http_clientrequest
You have to listen for the "end" event and concat all chunks from the "data" event togehter for the full body response.
const express = require('express');
const app = express();
const https = require('https');
const url = "https://api.thevirustracker.com/free-api?countryTimeline=US";
app.get("/", (req, res) => {
res.send("Server is Running")
https.get(url, (response) => {
const chunks = [];
response.on("data", (data) => {
chunks.push(data);
})
response.on("end", () => {
let size = chunks.reduce((prev, cur) => {
return prev + cur.length;
}, 0);
let data = Buffer.concat(chunks, size).toString();
console.log(JSON.parse(data))
});
})
})
app.listen(3000, () => console.log("Server is Running 0n 5000"));
why are you using https?
replace https with http and run it again.
const express = require('express');
const app = express();
const http = require('http');
const url = "https://api.thevirustracker.com/free-api?countryTimeline=US";
app.get("/", (req ,res) => {
res.send("Server is Running")
http.get(url, (response) => {
response.on("data", (data) => {
const TimelineData = JSON.parse(data);
console.log(TimelineData);
})
})
})
const express = require('express')
const app = express()
const port = 3000
app.post('/', (req, res) => {
res.send('Hello World!")
})
app.listen(port, () => {
console.log('server running')
})
When you run the program in nodejs, open the brower and type http://localhost:3000. The output will be....
Listen for 'end ' the problem will be resolved
Try importing all the dependencies. Importing is better than requiring because you can selectively load only the pieces you need. Also in package.json file add "type":"module" before scripts. The days of const something= require('something') are a thing of the past now because of new ESM modules.
import express from 'express';
import https from 'https';
const app=express();
const port=3000;
In package.json file
"name": "restApiWithNode",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
Read this article for clarity https://formidable.com/blog/2021/node-esm-and-exports/
My websocket server, based on node.js, works for ws:// but not for wss://
The server runs on my Raspberry Pi B 3+. Now that I have changed ws:// to wss:// in my JavaScript file, it does not work anymore.
The node.js server:
const WebSocket = require('ws');
var wss = new WebSoket.Server({ port: 4445 });
wss.on('connection', function connection(ws) {
console.log("New client connected.");
ws.on('message', function incoming(data) {
console.log(data);
ws.close();
});
ws.on('close', function close() {
console.log("Client disconnected.");
});
});
The JavaScript client:
var connection = new Websocket('wss://myDomain:4445');
connection.onopen = function () {
connection.send("Hello");
connection.close();
}
connection.onerror = function (error) {
console.log(error);
connection.lose();
}
'myDomain' is a subdomain that refers to the IP of the Raspberry Pi via dns.
I get the following error:
WebSocket connection to 'wss://myDomain:4445/' failed: Error in
connection establishment: net::ERR_CONNECTION_CLOSED
Maybe it will help you
Example:
Node server.js
const express = require("express");
const http = require("http");
const socketIo = require("socket.io");
const axios = require("axios");
const port = process.env.PORT || 4445;
const index = require("./routes/index");
const app = express();
app.use(index);
const server = http.createServer(app);
const io = socketIo(server);
let interval;
io.on("connection", socket => {
console.log("New client connected");
if (interval) {
clearInterval(interval);
}
interval = setInterval(() => getApiAndEmit(socket), 10000);
socket.on("disconnect", () => {
console.log("Client disconnected");
});
});
const getApiAndEmit = async socket => {
try {
const res = await axios.get(
"https://b.application.com/api/v1/scores?expand=createdBy"
);
socket.emit("FromAPI", res.data); // Emitting a new message. It will be consumed by the client
} catch (error) {
console.error(`Error: ${error.code}`);
}
};
server.listen(port, () => console.log(`Listening on port ${port}`));
Client in React
import socketIOClient from "socket.io-client";
class App extends Component {
constructor (props) {
super(props);
this.state = {
scores: []
endpoint: "http://127.0.0.1:4445"
}
}
componentDidMount() {
const { endpoint } = this.state;
const socket = socketIOClient(endpoint);
socket.on("FromAPI", data => this.setState({ scores: data }));
}
render () {
<div>
</div>
)
}
}
export default App;
For example I have this URL: http://localhost/chat.html?channel=talk
How can I get the value of parameter channel in Node.js?
I want to store the value of channel in a variable.
I changed server.get to this:
server.get("/channel", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(req.query.channel);
let rueckgabe = {
channel: req.query.channel
};
res.send(JSON.stringify(rueckgabe));
});
Now I'm expecting an output of the value of channel on my console but nothing appears.
This is the full code of index.js:
//Server erstellen
const express = require("express");
let server = express();
server.use(express.static("public"));
//Socket.io
const http = require("http");
let httpServer = http.Server(server);
const socketIo = require("socket.io");
let io = socketIo(httpServer);
//Eventlistener bei Verbindungsaufbau
io.on("connection", (socket) => {
console.log(socket.id);
socket.on("chatnachricht", eingabe => {
io.emit("nachricht", eingabe);
});
});
let stdIn = process.openStdin();
stdIn.addListener("data", (eingabe) => {
io.emit("nachricht", eingabe.toString());
});
server.get("/channel", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(query);
let rueckgabe = {
channel: query.channel
};
//res.send(JSON.stringify(rueckgabe));
res.send(JSON.stringify(rueckgabe));
});
httpServer.listen(80, () => {
console.log("Server läuft");
});
SOLUTION
This code works so far but with limitations:
//Server erstellen
const express = require("express");
let server = express();
server.use(express.static("public"));
const http = require("http");
let httpServer = http.Server(server);
const socketIo = require("socket.io");
let io = socketIo(httpServer);
var router = express.Router();
const url = require("url");
var path = require('path');
//Eventlistener bei Verbindungsaufbau
io.on("connection", (socket) => {
console.log(socket.id);
socket.on("chatnachricht", eingabe => {
io.emit("nachricht", eingabe);
});
});
/*
let stdIn = process.openStdin();
stdIn.addListener("data", (eingabe) => {
io.emit("nachricht", eingabe.toString());
});
*/
server.get("/chat", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(query.channel);
let rueckgabe = {
channel: query.channel
};
res.sendFile('chat.html', { root: path.join(__dirname, 'public/') });
//res.send(JSON.stringify(rueckgabe));
});
httpServer.listen(80, () => {
console.log("Server läuft");
});
Now it works with server.get() but I can't use both res.sendFile('chat.html', { root: path.join(__dirname, 'public/') }); and res.send(JSON.stringify(rueckgabe));. How can I use both?
It looks like you're using the Express framework for Node.
From the docs, query string params may be accessed via req.query:
server.get("/channel", (req, res) => {
let id = req.query.id; // where "id" is a paramter on the query string
}
And if you need the full URL of the request:
server.get("/channel", (req, res) => {
let fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
}
Well you mentioned for this url http://localhost/chat.html?channel=talk you're not seeing the channel parameter in the server. That's because you aren't hitting the endpoint that you've defined.
Copy of your code from above
server.get("/channel", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(req.query.channel);
let rueckgabe = {
channel: req.query.channel
};
res.send(JSON.stringify(rueckgabe));
});
You're setting the /channel url here. With this configuration if you want to get the query parameter you need to call http://localhost:{portnumber}/channel?channel=somerandomvalue
If you want to have the /chat url change your configuration like this:
server.get("/chat", (req, res) => {
let query = url.parse(req.url, true).query;
console.log(req.query.channel);
let rueckgabe = {
channel: req.query.channel
};
res.send(JSON.stringify(rueckgabe));
});
and call into http://localhost:{portnumber}/chat?channel=somerandomvalue
If you want to serve a static html while using the url name as the same file name you can do something like this:
var router = express.Router();
var path = require('path');
router.get('/chat', function(req, res) {
// where chat.html is in the public directory
console.log(req.query.channel);
res.sendFile('chat.html', { root: path.join(__dirname, '../public/') });
});