How to get value of URL parameter in Node.js? - javascript

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/') });
});

Related

Node spits out this random error, I cant see the problem in my code

I am working on a esp32 wifi speaker, I got the board going, and now I need to make a server from where you can stream what songs you'd like. I'm new to working on the backend and i'm having trouble with this error: node:internal/errors:465 ErrorCaptureStackTrace(err);
Here is my code:
const fs = require("fs");
const ytdl = require("ytdl-core");
const express = require("express");
var cors = require("cors");
var path = require("path");
const app = express();
var http = require("http").createServer(app);
const io = require("socket.io")(http);
const bodyParser = require('body-parser');
const port = process.env.PORT || 8080;
const adress = '127.0.0.1';
var clientGlob = null;
var destDir = "./Music";
var songs = [];
var songDur = [];
var playing = false;
var curSong = '';
app.use(express.json()); // to support JSON-encoded bodies
app.use(express.urlencoded({ extended: true })); // to support URL-encoded bodies
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname,"index.html"));
});
app.post("/downAudio", (req, res) => {
getAudio(req.body.url, res);
});
getAudio = (videoURL, res) => {
console.log(videoURL);
var stream = ytdl(videoURL, {
quality: "highestaudio",
filter: "audioonly",
})
var videoReadableStream = ytdl(videoURL, { filter: 'audioonly'});
ytdl.getInfo(videoURL).then((info) => {
console.log("title:", info.videoDetails.title);
console.log("rating:", info.player_response.videoDetails.averageRating);
console.log("uploaded by:", info.videoDetails.author.name);
var videoName = info.videoDetails.title.replace('|','').toString('ascii');
var videoWritableStream = fs.createWriteStream(destDir + '\\' + videoName + '.mp3');
var stream = videoReadableStream.pipe(videoWritableStream);
stream.on('finish', function() {
res.writeHead(204);
res.end();
});
console.log("File downloaded and added to the queue");
songs.push(destDir + '\\' + videoName + '.mp3');
var duration = parseInt(info.videoDetails.lengthSeconds);
songDur.push(duration*1000);
console.log("Audio added to the queue")
if(!playing)
play();
});
};
play = ()=>{
playing=true;
curSong=songs[0];
setTimeout(playNext(),songDur[0]);
}
playNext = ()=>
{
fs.unlink(curSong, function (err) {
if (err) throw err;
console.log('File deleted!');
});
songs.pop()
songDur.pop();
if(songs.length!=0)
play();
else
playing=false;
}
io.on("connection", (client) => {
clientGlob = client;
console.log("User connected");
});
app.listen(port,adress, () => {
console.log(`Server started, link: ${adress}:${port}`);
});
It downloads the songs fine but it has a problem in the playnext function. I cant relate this error to anything in there. What am I doing wrong?
Also any help into improving the code and performance is welcome.
If needed I will provide more information, thanks!
Fixed the problem, for some reason it didn't like the type of function I used. After making it a normal function playnext(){}... it worked.

How to get parameter from URL in express without getting into request

const express = require('express');
const app = express();
app.use('/', anyroute);
// in anyroute file
router.route('/:id').get(controlFunction)
controlFunction(req, res, res)=> {
// Here we can get the "id" from the variable with req.param.id
}
but I want to use the "id" before getting into this controller function. Like this
modifyFunction(userId)=> {
// Do something with the userId
}
router.route('/:id').get(modifyFunction(id), controlFunction)
Is it possible in express and javascript to retrieve the 'id' from url and use in modifyFunction(id) before getting into the request.
In an express middleware req and res variables are transferred from one middleware to next. But I created a function function(type, id) which returns a middleware function(req, res, next). in this function(type, id) type parameter will be passed manually and id from URL.
router
.route('/all-contacts/:id')
.get(authController.isLoggedIn, viewController.getAxiosConfig('contactNameEmail', id), viewController.getAllContact);
exports.getAxiosConfig = (type, id) => {
return (req, res, next) => {
const config = axiosConfig(type, id);
const accessToken = req.cookies.access_token;
const tokenArray = config.headers.Authorization.split(' ');
tokenArray.splice(1, 1, accessToken);
const newToken = tokenArray.join(' ');
config.headers.Authorization = newToken;
req.config = config;
next();
};
};
exports.getAllContact = catchAsync(async (req, res, next) => {
// const token = req.cookies.access_token;
// console.log(token);
// const config = axiosConfig('contactNameEmail');
req.config.method = 'GET';
// const tokenArray = config.headers.Authorization.split(' ');
// tokenArray.splice(1, 1, token);
// const newToken = tokenArray.join(' ');
// config.headers.Authorization = newToken;
const contacts = await axios(req.config);
console.log(req.config);
const { data } = contacts;
res.status(200).render('contactList', {
title: 'All contacts',
data
});
});
You can access the ID in the middleware, which is called before the route handler.

JSON.parse() Returning Unexpected end of input

[`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/

How I send a compare a hash in express? server to client

I need to answer the client when they ask for a hash from the server which is used to generate and authorize for access to files, how can I confirm that the hash is equal to the message, using node.js and express:
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const sha1 = require('sha1');
const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended: true}));
app.get('/', function(request, response) {
var x1 = request.query.x1;
var x2 = request.query.x2;
var x3 = request.query.x3;
var x4 = 654321;
var hash = sha1(x2+x3+x4)
});
app.listen(process.env.PORT || 3000, function() {
console.log("Server is running in port 3000!");
});
You can use the crypto module to generate and decode the hash. Here is an example.
const resizedIV = Buffer.allocUnsafe(16)
app.get('/', function(request, response) {
const key = crypto
.createHash("sha256")
.update('secret-key')//this should be a secret key
.digest()
const cipher = crypto.createCipheriv("aes256", key, resizedIV)
for (var prop in req.query) {
if (req.query.hasOwnProperty(prop)) {
cipher.update(req.query[prop], "binary", "hex")
}
}
const hash = cipher.final("hex")
res.send(hash)
});
and then you can decode it like this
app.get('/decode', function(req, res) {
const key = crypto
.createHash("sha256")
.update('secret-key')
.digest()
const decipher = crypto.createDecipheriv("aes256", key, resizedIV),
decipher.update(req.query.hash, "hex", "binary")
const decoded = decipher.final("binary")
res.send(decoded)
})

Returning String with Express post

I have this app.js file:
let express = require('express')
let app = express()
let Clarifai = require('clarifai')
app.use(express.urlencoded({extended: true}))
app.use(express.static('./public'))
let link = app.post('/route', (req, res) => {
let linkString = req.body.link
res.send(JSON.stringify(linkString))
})
app.listen(3000)
const capp = new Clarifai.App({
apiKey: 'MyAPIKeyIsHere'
});
predict = capp.models.initModel({id: Clarifai.FOOD_MODEL, version: "aa7f35c01e0642fda5cf400f543e7c40"})
.then(generalModel => {
return generalModel.predict(link)
})
.then(response => {
var concepts = response['outputs'][0]['data']['concepts']
console.log(concepts)
})
console.log('Express app running on port 3000')
console.log(link)
I am trying to return a string from the app.post method but it returns a JSON file. How should I do it exactly?
You can explicitly set the content type to text/html, before sending the data.
res.set('Content-Type', 'text/html');
res.send(JSON.stringify(linkString));
Are you sure that req.body.link is a string? If yes you could just pass linkString variable in send:
let link = app.post('/route', (req, res) => {
let linkString = req.body.link
res.send(linkString)
})

Categories

Resources