Url encode in NodeJs - node.js

I have a nodejs piece of code where am trying to do a db.get to cloudant trying to build the URL.
var contactsFile = result.docs[0]._id;
var finalUrl = contactsFile+'/'+contactsFile;
testDb.get(urlencode.decode(finalUrl), function(err, data) {
if (!err) {
abc = data;
console.log("file" , abc);
}
else{
console.log("this is the error " , err);
}
});
When i try to print the URL that is passed the get request, the URL is passed as
https://cloudant/db/contactsFile%2FcontactsFile.
But I want to pass it as https://cloudant/db/contactsFile/contactsFile.
I have tried uriencode and decode and tried what i understood, but when i print with urlencode.decode it shows / and in the get request no matter wat i do it gets converted to %2F.
This might be a simple question but as I am new to node I am still learning.

If I understood correctly you are now passing "https://cloudant/db/contactsFile%2FcontactsFile" to your testDb.get, but you'd need to pass "https://cloudant/db/contactsFile/contactsFile".
If that's so you could try this:
testDb.get(decodeURIComponent(finalUrl), ...);
For further reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent

Related

GET or POST from express do not parse a "percent sign" request

I am having difficulties in parsing an HTTP request that uses a "%26" instead of a "&" character.
Context: I am trying to receive an HTTP request made by an IP camera that has a limitation where it cannot send the '&' character, so I have to set it up using '%26' to separate parameters, so the camera is making a POST request like this:
http://192.168.45.4:8000/test?foo=me%26bar=them
To process this request on my server side, I have this simple function:
Broker.all("*", (req,res) => {
console.log("foo=" + req.query.foo);
console.log("bar=" + req.query.bar);
console.log("Received a generic put request");
res.send("Processed");
});
This code is working fine when I make a request using the '&' character.
This is the result to the request: http://192.168.45.4:8000/test?foo=me&bar=them
foo=me
bar=them
Received a generic put request
This is the result to the request: http://192.168.45.4:8000/test?foo=me%26bar=them
foo=me&bar=them
bar=undefined
Received a generic put request
I have been banging my head for the past... (ashamed)... nevermind how many hours, I am not sure what I am doing wrong.
I'm pretty sure this is easy, but I really couldn't find it on the forums, maybe because I wasn't able to search specifically for "%26" in the posts.
Any help would be appreciated.
EDIT after being solved
As suggested by GPack, I used his parser code, and it seems to be working. Just need to make sure to check beforehand if the Generic URL does have parameters or not.
I still believe there might be a more natural way to do this with express...
This is the new code with the parser which is working:
broker.all("*", (req,res) => {
const list = req.originalUrl.split("?")[1].split("%26");
const params = list.reduce((obj, str) => {
const parts = str.split("=");
obj[parts[0]] = parts[1];
return obj;
}, {});
console.log(params); // { bar: "them", foo: "me" }
console.log("foo=" + params.foo);
console.log("bar=" + params.bar);
console.log("Received a generic put request");
res.send("I'm just a simple broker");
});
I tried using decodeURI & decodeURIComponent but in vain.
So I wrote the parser myself:
// The request object should be something like this (with other attributes)
const req = {
originalUrl: "/test?foo=me%26bar=them"
}
// You may want to handle the case where a request doesn't have parameters
const list = req.originalUrl.split("?")[1].split("%26");
const params = list.reduce((obj, str) => {
const parts = str.split("=");
obj[parts[0]] = parts[1];
return obj;
}, {});
console.log(params); // { bar: "them", foo: "me" }

how to pass data and redirect in express

My code is
main.post('/userlist', function(req, res, next) {
// where did you get this?
// var db = req.db;
var query = connection.query("SELECT name,zaman,giriscikis FROM giriscikis where date_format(zaman,'%Y-%m-%d') between ? and ?", [req.body.bas, req.body.bitis], function(err, result) {
if (err) throw err;
console.log(result);
res.send(httpResponse(result));
return res.redirect('/zamansorgu');
//console.log(req.body.bas)
//console.log(req.body.bitis)
});
});
I want to fecth data from database and redirect to same page in the code(zamansorgu.html)
But I get an error
Cannot set headers after they are sent to the client
How can I solve this problem
thank you for your helps
You are attempting to send back JSON data and redirect to a different page. That's not possible. Each endpoint request can have one response, not more. You can either send back the data, or redirect. That's because redirecting really does send back data too (the html of the new target page).
Think about it from the caller's point of view. If it did allow this how would it work? If someone uses this link from a browser should the browser show the JSON data you returned, or should it take the user to the new page?
The error is saying "hey, I already sent back data. I can't redirect now because we are already down the path of returning some JSON".
If you want to use the data to format the output that can be done, or if you want to redirect to a new location and pass the data in the url, that's also possible. Consider code like this:
main.post('/userlist', function(req, res, next) {
// var db = req.db;
var query = connection.query("SELECT name,zaman,giriscikis FROM giriscikis where date_format(zaman,'%Y-%m-%d') between ? and ?", [req.body.bas, req.body.bitis], function(err, result) {
if (err) return next(err);
if (result.urlparam) {
// this builds a new url using the query value
const nextUrl = `/zamansorgu?param=${result.urlparam}`;
return res.redirect(nextUrl);
}
else {
// this builds html here
const html = `<html><body><h1>${result.title}</h1></body></html>`;
return res.send(html);
}
});
});
I also ran into this, in my case it was quite a deceptive little bug. A node-inspector session helped me pinpoint the problem quickly however. The problem in my case was pretty bone-headed, the res.end call in the sample below is the offending line.
res.writeHead(200, {"Content-Type": "application/json"});
res.end(JSON.stringify(someObject));
someObject did not exist after a refactor and that was causing a ReferenceError to get thrown. There is a try-catch in Router.prototype._dispatch that is catching the ReferenceError and passing it into next
res.status(301).redirect(`/zamansorgu?name=${"John"}&email=${"john#email.com"}`)
So, this is something I explored but it will be dependent on the structure of your application. You could always pull the data out using query params and hydrate your application.

Memorize twitter data response in nodejs

I'm doing a web application that after posting some tweets it return informations like number of retweets etc.
The problem I'm having is that I'm unable to store the data returned by the twitter api.
The twitter function to load the data from the API is:
exports.loadTwit = function(){
return function(req,res,next){
let responseDataObject = [];
req.twitter.forEach(function(entry) {
T.get('statuses/show/'+entry.id,loaded);
});
async function loaded(error, data, response){
if (error) {
console.log(error);
}else{
dati = await data;
responseDataObject.push(dati);
console.log(responseDataObject); // shows the data
}
}
console.log(responseDataObject); // shows []
res.render('db',{dati: responseDataObject});
}
}
I want to store the data in the responseDataObject. I've put the async/await because I think it's asyncronous so I have to wait for the data.
The problem, showed in the comments, is that inside the loaded function I can see the content of responseDataObject, outside it gives me an empty array.
I don't know how to solve it, any help is appreciated.
Thanks

Node.js read json from google api

i try to get google suggestion from this url http://suggestqueries.google.com/complete/search?q=bob&client=firefox
when i run the url i get this result : ["bob",["bobby shmurda","bob marley","bobbi kristina","bobbi brown","bobbi kristina brown","bob dylan","bob evans","bobby hurley","bob\u0027s burgers","bob seger"]]
in node.js i used request , heres my code :
var request = require('request');
var url = 'http://suggestqueries.google.com/complete/search?q=bob&client=firefox';
request(url,function(error, response, result){
if(!error){
console.log(result);
}
});
until now everythings work fine
as you can see my output is an array with two values, in above code when i try to get result[1]instead of show array its just show a ".
i dont know why this happen.
probably because you get a String and not a JSON.
try JSON.parse
result = JSON.parse(result)
try to parse it first
var json_data = JSON.parse(result);

check on server side if youtube video exist

How to check if youtube video exists on node.js app server side:
var youtubeId = "adase268_";
// pseudo code
youtubeVideoExist = function (youtubeId){
return true; // if youtube video exists
}
You don't need to use the youtube API per-se, you can look for the thumbnail image:
Valid video = 200 - OK:
http://img.youtube.com/vi/gC4j-V585Ug/0.jpg
Invalid video = 404 - Not found:
http://img.youtube.com/vi/gC4j-V58xxx/0.jpg
I thought I could make this work from the browser since you can load images from a third-party site without security problems. But testing it, it's failing to report the 404 as an error, probably because the content body is still a valid image. Since you're using node, you should be able to look at the HTTP response code directly.
I can't think of an approach that doesn't involve making a separate HTTP request to the video link to see if it exists or not unless you know beforehand of a set of video IDs that are inactive,dead, or wrong.
Here's an example of something that might work for you. I can't readily tell if you're using this as a standalone script or as part of a web server. The example below assumes the latter, assuming you call a web server on /video?123videoId and have it respond or do something depending on whether or not the video with that ID exists. It uses Node's request library, which you can install with npm install request:
var request = require('request');
// Your route here. Example on what route may look like if called on /video?id=123videoId
app.get('/video', function(req, response, callback){
var videoId = 'adase268_'; // Could change to something like request.params['id']
request.get('https://www.youtube.com/watch?v='+videoId, function(error, response, body){
if(response.statusCode === 404){
// Video doesn't exist. Do what you need to do here.
}
else{
// Video exists.
// Can handle other HTTP response codes here if you like.
}
});
});
// You could refactor the above to take out the 'request.get()', wrap it in a function
// that takes a callback and re-use in multiple routes, depending on your problem.
#rodrigomartell is on the right track, in that your check function will need to make an HTTP call; however, just checking the youtube.com URL won't work in most cases. You'll get back a 404 if the videoID is a malformed ID (i.e. less than 11 characters or using characters not valid in their scheme), but if it's a properly formed videoID that just happens to not correspond to a video, you'll still get back a 200. It would be better to use an API request, like this (note that it might be easier to use the request-json library instead of just the request library):
request = require('request-json');
var client = request.newClient('https://www.googleapis.com/youtube/v3/');
youtubeVideoExist = function (youtubeId){
var apikey ='YOUR_API_KEY'; // register for a javascript API key at the Google Developer's Console ... https://console.developers.google.com/
client.get('videos/?part=id&id='+youtubeId+'&key='+apikey, function(err, res, body) {
if (body.items.length) {
return true; // if youtube video exists
}
else {
return false;
}
});
};
Using youtube-feeds module. Works fast (~200ms) and no need API_KEY
youtube = require("youtube-feeds");
existsFunc = function(youtubeId, callback) {
youtube.video(youtubeId, function(err, result) {
var exists;
exists = result.id === youtubeId;
console.log("youtubeId");
console.log(youtubeId);
console.log("exists");
console.log(exists);
callback (exists);
});
};
var notExistentYoutubeId = "y0srjasdkfjcKC4eY"
existsFunc (notExistentYoutubeId, console.log)
var existentYoutubeId = "y0srjcKC4eY"
existsFunc (existentYoutubeId, console.log)
output:
❯ node /pathToFileWithCodeAbove/FileWithCodeAbove.js
youtubeId
y0srjcKC4eY
exists
true
true
youtubeId
y0srjasdkfjcKC4eY
exists
false
false
All you need is to look for the thumbnail image. In NodeJS it would be something like
var http = require('http');
function isValidYoutubeID(youtubeID) {
var options = {
method: 'HEAD',
host: 'img.youtube.com',
path: '/vi/' + youtubeID + '/0.jpg'
};
var req = http.request(options, function(res) {
if (res.statusCode == 200){
console.log("Valid Youtube ID");
} else {
console.log("Invalid Youtube ID");
}
});
req.end();
}
API_KEY is not needed. It is quite fast because there is only header check for statusCode 200/404 and image is not loaded.

Resources