I have made a nodejs script to upload css files to our web application. I've omitted everything that's not necessary:
var downloadCSS = function() {
var download = wget.download(src, output, options);
download.on('end', function(outputMessage) {
var unzipStream = fs.createReadStream(output).pipe(unzip.Extract({ path: path }));
unzipStream.on('close', function() {
findFilesAsync(path);
});
});
}
var findFilesAsync = function(path) {
for (var vendor in searchList) {
(function(filePath, vendor, loginCredentials){
glob(filePath, function(err, files) {
login(loginCredentials, files[0], vendor);
})
})(filePath, vendor, loginCredentials);
}
};
var login = function(credentials, file_local, vendor) {
request.post(
'https://server',
function(error, response, body) {
getSettings(cookie, file_local, vendor);
}
);
};
var getSettings = function(cookie, file_local, vendor) {
request.get(
'https://server',
function(error, response, body) {
fileUpload(cookie, settings, file_local, vendor);
}
);
};
var fileUpload = function(cookie, settings, file_local, vendor) {
var CSS_file = fs.createReadStream(file_local);
CSS_file.on('error', function(err) {
console.log('error at reading CSS file');
});
request.post(
'https://server',
function(error, response, body) {
setSettings(cookie, settings, vendor);
}
);
};
var setSettings = function(cookie, settings, vendor) {
request.put(
'https://server',
function(error, response, body) {
logout(cookie, settings, vendor);
}
);
};
var logout = function(cookie, settings, vendor) {
request.get(
'https://server',
function(error, response, body) {
}
);
};
To upload a css file the functions get called top to bottom if there is no error:
downloadCSS()
findFilesAsync()
login()
getSettings()
fileUpload()
setSettings()
logout()
There are 5 CSS files, so whenever a file is found in the findFilesAsync() function, a new login() function will be called asyncronously.
I know this can be done cleaner with promises, but I don't know where to start?
Take a look at this MDN Promise reference they have given a nice example function for http requests that uses promises. So in order to avoid callbacks you will have to change/modify your request class
Related
I am writing code in node.js where i want to read from a file and then export it to a web api. The problem is that I get an error on the code when i am using let.
The error appears to be in my function "render_html my views.js file:
"use strict";
const fs = require('fs');
const model = require('./model');
exports.car = (request, response, params) => {
if (Object.keys(params).length === 0) {
render_JSON(response, model.cars())
}else{
render_JSON(response, model.cars(parseInt(params.number)))
}
};
function render_html(response, file) {
fs.readFile(file, (err, data) => {
if (err) {
console.error(err)
} else {
response.write(data);
response.end();
}
});
}
function render_JSON(response, object) {
const responseJSON = JSON.stringify(object);
response.write(responseJSON);
response.end()
}
I also have problem in "function setHeaders" in router.js file:
"use strict";
const views = require('./views');
const url = require('url');
const routes = [
{
url: ['/api/cars'],
view: views.car,
methods: ['GET'],
headers: {'Content-Type': 'application/json; charset=UTF-8'} // application/json as per RFC4627
}];
function setHeaders(response, headers = {'Content-Type': 'text/plain'}, code = 200) {
response.writeHeader(code, headers);
}
// Filters trailing slash in the url
// for example allowing /api/cars and /api/cars/ to be treated equally by removing trailing slash in the second case
function filterURL(requestURL) {
if (requestURL.pathname.endsWith('/')) {
requestURL.pathname = requestURL.pathname.replace(/\/$/, '');
}
}
exports.route = (request, response) => {
for (let r of routes) {
const requestURL = url.parse(request.url, true);
// url matched and correct method
//if requestURL.pathname
filterURL(requestURL);
if (r.url.includes(requestURL.pathname) && r.methods.includes(request.method)) {
if (r.headers) {
setHeaders(response, r.headers);
} else {
setHeaders(response)
}
r.view(request, response, requestURL.query);
return;
}// if unsupported HTTP method
else if (r.url.includes(requestURL.pathname) && !r.methods.includes(request.method)) {
setHeaders(response, undefined, 405);
response.end();
return;
}
}
// if route not found respond with 404
setHeaders(response, undefined, 404);
response.end('404 Not Found!')
};
Somebody knows what the problem could be?
thanks.
about your problem in "render_html" function I think the problem is you are missing the encoding of the file, as fs doc says if you dont set a encoding the result will be a buffer. You can easy fix it using:
fs.readFile(file, 'utf8', callback)
(Assuming that you are using utf8 as encoding)
And I think your problem in "router.js" file is you should use "writeHead" instead "writeHeader" you can check it in http doc.
I hope it solves your issue, greetings.
I am making a skill for the Amazon Echo. In my handlers, I have an intent (SelectGardenIntent) that obtains the user_id (needed for following HTTP requests) from the access token successfully, as well as a variable called gardenNumber which is a slot value. To complete the request, I need two other values, the garden_id and the dev_id. I use this gardenNumber and pass it into a function called getGardenId, which will assign the one of the data from the HTTP request to the variable garden_id I have defined in index.js. There are no issues with user_id and gardenNumber. When the function is run, there are no errors from the request, but the callback function with the response is also not executed. The user_id, "about to enter request", and "req done" are correctly logged when tested, but the other log statements in the callback function are not since it is not run. The result is that garden_id is undefined. dev_id is obtained in another method that depends on this garden_id, so dev_id is also undefined. Please help me on this issue. I have pasted the relevant code below.
...
var user_id, garden_id, dev_id;
...
function getGardenId (gardenNumber) {
console.log(user_id);
var path = '/api/rest/client/getgardeninfo?&userid=' + user_id;
var options = {
hostname: server_ip,
port: 80,
path: path,
method: 'GET'
}
console.log("about to enter request");
var req = http.request(options, (res) => {
console.log('entered request');
if (res.statusCode === 200) {
console.log('successful request');
res.setEncoding('utf8');
var body = "";
res.on('data', (chunk) => {
console.log('adding data');
body += chunk.toString();
});
res.on('end', () => {
var obj = JSON.parse(body);
console.log('successfully parsed');
if (obj.error === 200) {
console.log('##gardenid successfully obtained');
garden_id = obj.data[gardenNumber - 1].id;
} else {
console.log("parsing error");
}
});
} else {
console.log("failed request");
}
}); } catch(e) {
console.log("ERROR");
}
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
req.on('finish', () => {
console.log('ended');
})
req.end();
console.log("req done");
}
...
var handlers = {
...
'SelectGardenIntent': function () {
//var filledSlots = delegateSlotCollection.call(this);
var gardenNumber = this.event.request.intent.slots.Garden.value;
user_id = this.event.session.user.accessToken;
getGardenId(gardenNumber);
getDevId(garden_id);
this.emit(':tell', `OK, garden ${gardenNumber} selected, user id is ${user_id}, garden id is ${garden_id}, device id is ${dev_id}`);
}
...
}
You'd better use npm request to make calls.
request.get({
url: 'http://' + server_ip + '/api/rest/client/getgardeninfo?&userid=' + user_id
}, function (err, res, body) {
console.log(body);
})
I am using Diffbot analyze API for detecting the page type and I want result like
this
{"stats":{"times": {"docParseTime":0,"docGlobalsTime":0,"fetchAndRenderTime":586,"typeTime":0},"fromCache":true,"types":{"recipe":0,"discussion":0,"audio":0,"error":0,"location":0,"faq":0,"image":0,"job":0,"download":0,"game":0,"product":0,"frontpage":0,"document":1,"article":0,"event":0,"chart":0,"serp":0,"reviewslist":0,"video":0,"profile":0}},"request":{"pageUrl":"http://www.irs.gov/pub/irs-pdf/fw4.pdf","api":"analyze","version":3,"options":["stats"]},"type":"other","objects":[]}
but currently I am getting like
this
{"request":{"pageUrl":"http://static.nfl.com/static/content/public/image/rulebook/pdfs/2013%20-%20Rule%20Book.pdf","api":"analyze","version":3},"type":"other","objects":[]}
I have to pass 'stats' argument in request.
But where in request, I can pass this argument.
Thanks,
Hi I got it and here is the solution, just customize the Diffbot lib file or write in your file its up to you, and here is the code
var diffbot = new Diffbot('xxxxxxxxxxxxxxxxx');
diffbot.analyze({
uri: "http://www.visitcalifornia.in/media/pages/getting_around/maps/ORANGE-COUNTY.pdf",
html: true,
comments: true,
stats: true
}, function(err, response) {
}
And here is the customize library code
Diffbot.prototype.analyze = function (options, callback) {
for (var i in options) {
this[i] = options[i];
}
var options = this;
// support 'url'
if (options.url) {
options.uri = options.url;
delete options.url;
}
if (!options.uri) {
throw new Error("the URI is required.");
}
var diffbot_url = "http://api.diffbot.com/v3/analyze?token=" + this.token + "&url=" + encodeURIComponent(options.uri)+"&fields=stats";
if (options.stats) {
diffbot_url += "&stats=1";
}
request({uri: diffbot_url}, function(error, response, body) {
if (error) {
callback(error, undefined);
} else {
callback(false, JSON.parse(body));
}
});
}
it works as charm!
For a personal project I'm trying to create a simple oEmbed system using Nodejs.
My route looks like this:
app.get('/oembed/:url', function (req, res) {
oembed.get(req.params.url, function (error, result) {
return res.json(200, {message: "OK"});
});
});
and oembed is exposed using var oembed = require('../oembed');
For the oembed.js itself I have:
var request = require('request');
exports.get = function(url, callback) {
//this bit will be developed to call different functions depending on the URL
html = vimeo(url)
};
function vimeo(url) {
var videoUrl = url;
var endpoint = 'http://www.vimeo.com/api/oembed.json';
var url = endpoint + '?url=' + encodeURIComponent(videoUrl) + '&width=640';
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
var video = JSON.parse(body);
return video.html
}
})
}
So far, the vimeo function returns the desired html to the function call but I'm a bit lost from here. I'm not sure how I return the html to the initial request (the oembed.get part) and utilise the callback's error and result parameters.
Any help (and advice) would be much appreciated.
It seems you just don't understand how callback functions work. You need something like this in your oembed.js file:
var request = require('request');
exports.get = function(url, callback) {
var endpoint = 'http://www.vimeo.com/api/oembed.json';
request(endpoint + '?url=' + encodeURIComponent(url) + '&width=640', function (error, response, body) {
if (!error && response.statusCode == 200) {
try {
callback(null, JSON.parse(body).html);
} catch (error) {
callback(error);
}
}
});
};
And your route should look like this:
app.get('/oembed/:url', function (req, res) {
oembed.get(req.params.url, function (error, result) {
if (error) {
res.json(500, {message: error});
} else {
res.json(200, {message: "OK"});
}
});
});
Weird error, I use blueimp jquery file upload, to upload files from client-side to Node.js then Amazon S3 storage.
the code works perfect, the files does get to Amazon s3, but on client-side on the plugin I get this error: Error SyntaxError: Unexpected token S.
The Node.js code I'm using is the following:
app.post('/upload', function(req, res) {
fs.readFile(req.files.files[0].path, function (err, data) {
var imageName = req.files.files[0].name
/// If there's an error
if(!imageName){
console.log("There was an error")
res.redirect("/");
res.end();
} else {
var img_path = req.files.files[0].path;
var file_read = fs.readFile(img_path, function(err, data){
var BucketName = 'webwedding/'+SSName;
s3.createBucket({Bucket: BucketName}, function() {
var params = {Bucket: BucketName,ACL: "public-read" , Key: imageName, Body: data};
s3.putObject(params, function(err, data) {
res.writeHead(200, {'Content-Type': 'text/plain'});
if (err) {
console.log(err)
res.end(err);
}
else {
console.log('Uploaded ' + imageName +' To '+SSName);
res.end('Successfully uploaded data to webwedding\n');
}
});
});
});
}
});
});
I now came to understand that I need to JSON.stringly the result, but only cant manage to create the correct res.end result! trying to follow Blueimp support.
*Edit:*trying to add template to check results:
var files = [
{
"name": "picture1.jpg",
"size": 902604,
"url": "http:\/\/example.org\/files\/picture1.jpg",
"thumbnailUrl": "http:\/\/example.org\/files\/thumbnail\/picture1.jpg",
"deleteUrl": "http:\/\/example.org\/files\/picture1.jpg",
"deleteType": "DELETE"
}]
res.end(JSON.stringify(files));
gives me that error on client side:
Error Empty file upload result
The error comes from fileupload.ui code, hope it's not too long, but I think I must show it so maybe someone can figure it out:
if (data.context) {
data.context.each(function (index) {
var file = files[index] ||
{error: 'Empty file upload result'};
deferred = that._addFinishedDeferreds();
that._transition($(this)).done(
function () {
var node = $(this);
template = that._renderDownload([file])
.replaceAll(node);
that._forceReflow(template);
that._transition(template).done(
function () {
data.context = $(this);
that._trigger('completed', e, data);
that._trigger('finished', e, data);
deferred.resolve();
}
);
}
);
});