Show the available image in Node.js(when traffic limit exceeded) - node.js

I have an image hosting server that has a traffic limit 600M each day.
And I can also link the image with Google Drive. When I link the image with Google Drive, it's slow but there is no traffic limit.
So I want to let node.js server return the URL of the available image.
My image hosting domain is image.com and my node.js server's domain is node.com.
I'll insert image in HTML like this.
<img src = "http://node.js/image">
and node.js server's code is like below.
app.all('/image', function (req, res) {
if(// should check whether 'http://image.com/' is available now' //)
res.redirect('http://image.com/image.png');
else // The case that image.com is not available
res.redirect('http://googledrive/imagesourceURL');
});
So how can I know that image.com is available now?
If I check it by requesting the real image file, it will use traffic of image hosting server so I think it's not a good idea.
What should I insert in if(// should check whether 'http://image.com/' is available now' //)?
Do you have any idea about it?

In order to check if a http resourse i available you should do a http ajax request.
In your case you should redirect to that URL if the status is 200 and to the other URL otherwise.
It would be something like:
$.ajax({
type: "GET",
url: 'http://image.com/image.png',
success: function(data, textStatus, jqXHR){
console.log(textStatus + ": " + jqXHR.status);
res.redirect('http://image.com/image.png');
},
error: function(jqXHR, textStatus, errorThrown){
console.log(textStatus + ": " + jqXHR.status + " " + errorThrown);
res.redirect('http://googledrive/imagesourceURL');
}
});

Related

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. Unable to redirect different page than what it is supposed to be

In my program I am trying to make the server redirect the user to a different page if the wrong details of some sort are put in. The main problem that I am having is that whenever I try to use res.redirect() with another web page as a parameter I get the following error back: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I am not sure if I am referencing the web page in terms of where its stored on my computer wrong but something else about http headers was mentioned.
Here is my code that might potentially help to show what is wrong:
app.post("/profile.html", (req, res)=>
{
if(req.body.login_name == undefined)
{
var sql = "SELECT * FROM connectfour.players WHERE username =" + "'" + req.body.signup_name + "';";
connection.query(sql, function(error, results)
{
if(error) throw error;
if(results.length > 0)
{
console.log(res);
res.redirect("/start");
var already_taken = "username " + req.body.signup_name + " is already taken";
res.render("start", {already_taken});
}
else
{
var signup_name = req.signup_name;
res.render("profile", {signup_name});
}
});
}
So the form on another page posts the request for the profile.html page. Then something is checked to detect if the username is logging in or signing up. An SQL query happens with the data sent over. If the user already exists then the user will get sent over to a page that will make them try to signup again. This contains the res.redirect problem:
profile.ejs is what the page requested is supposed to be. But I need to redirect it to start.ejs if the if statement mentioning if(results.length > 0) happens. I would try to post an image showing what my problem is but the problem is that my reputation is not high enough.
You either call res.redirect or res.render. Both sets status and returns it and some info to a client. If '/start' is processed by some Express route handler (that renders using res.render("start", {already_taken});) when just redirect to it and that's all.

Cloudinary node.js progress of uploading

I used cloudinary in angularjs web SPA and there was nice callback named .progress:
.progress(function (info) {
//file.progress = Math.round((e.loaded * 100.0) / info.total);
//file.status = "Uploading... " + file.progress + "%"
console.log(info);
})
which was basically logging object with data about uploading status info.
Now I'm wondering if I'm able to somehow get same progress when uploading by nodeJS code on server side
cloudinary.v2.uploader.upload(path, { resource_type: "video" }, function(err, success) {
console.log('err: ' + JSON.stringify(err));
console.log('suc: ' + JSON.stringify(success.secure_url));
});
I'm using electron so I can communicate nodeJS side with front with ipcMain I can send custom event from node to front so I can just pass new event every 1% of uploading and display some progressbar on front.
But since cloduinary docs doesn't provide some additional info of how to get status of uploading with nodejs I don't know how to do that and if it is possible.
After much more googling I found information on github from cloudinary collaborator that progress isn't available for server-side uploading.

node.js simple HTTP server with content html not showing images

I am following along with the tutorials on The New Boston from Bucky and cant seem to get images to show up in the HTML file running a simple static index page in node.js
please note: this is a school project, I am tasked with doing this without using middle-ware such as express or connect which we have not reached yet. :D
var http = require('http');
var fs = require('fs');
var accessTime = new Date();
var accessCount = 0;
function send404Response(response) {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("Error 404: Page not found!");
response.end();
}
function onRequest(request, response) {
if (request.method == 'GET' && request.url == '/' ){
response.writeHead(200, {"Content-Type": "text/html"});
fs.createReadStream("./index.html").pipe(response);
fs.writeFileSync("logfile.txt", "\n Someone has accessed the index page \n" + accessTime + "\n ", "UTF-8",{'flags': 'a'});
console.log("A user made a request");
accessCount += 1;
console.log(accessCount + " page requests so far . . .");
}else {
send404Response(response);
}
}
http.createServer(onRequest).listen(8888);
console.log("Server is running...");
When I run it, the html page loads fine as localhost:8888 but no images will show up unless I use external images. for example the html would just have standard image tags?
<img src='photo.jpg' .... /> // doesnt work
<img src='http://www.AWebSite.com/photo.jpg' .... /> // naturally works
Thanks!!
Right, so at the moment you're not providing a code path for the images. Your first code block responds to 'http://localhost:8888/' and nothing else; you wouldn't even serve 'http://localhost:8888/index.html' if someone requested it.
If you want to serve all static content, then there's a few ways to go about it. To be the most web server-like, you'd probably start off by having a known folder with your static assets (e.g. ./public). Then you'd want to just take request.url and look for that under the public path using fs.stat(). If that path exists in that location, then you'd check the file extension to figure out the Content-Type header and serve it like you're doing now. If not, then you'd return a 404 like you are currently doing.
If you're not allowed to use third party libraries at all, I'd also recommend chunking each logical bit into its own file that you can require. If you can use third party libraries (just not middleware), then I'd say look into async.js to help the file handling workflow a bit, and to avoid callback hell.

How to set global variables by command

Thanks for so many fast response.
I used NodeJS(v4.3.2) and ExpressJs(v4.x) to build up website.
I used a lot AJAX and all AJAX url point to one static IP(AWS Server itself).
Because I would deploy to several servers, I don't want to change AJAX url separately.
My idea is when I run "node bin/www" command line, Can I change it to "node bin/www 50.50.50.50(my AWS address)" and I can set all AJAX url to the right IP?
Is it possible or other alternative solustion?
Thanks
Your issue is related to CORS : basically, you cannot access a domain http://www.example1.com from http://www.example2.com via Ajax if http://www.example1.com does not explicitly allows it in the response.
This is a "security" feature on most modern browsers. You won't encounter this problem using command line such as curl or chrome extension Postman.
To fix this, make sure the domain requesting the data (http://www.example2.com) is allowed in the Access-Control-Allow-Origin header in your server's response, as well as the http verb (GET, POST, PUT... or * for every http methods).
It all comes down to add the two following headers to the http://www.example1.com server's response :
Access-Control-Allow-Origin: http://www.example2.com
Access-Control-Allow-Methods: *
Edit
Following #Paulpro's comment, you have to rebase all your urls so that they reach your server's IP instead of your localhost server.
I fix this problem.
First, in bin/www
append these code to retrieve URL for command line and store into json file.
function setUpURL(){
var myURL = process.argv[2];
console.log('myURL: ', myURL);
var outputFilename = 'public/myURL.json';
var myData = {
port:myURL
}
fs.writeFile(outputFilename, JSON.stringify(myData, null, 4), function(err) {
if(err) {
console.log(err);
} else {
console.log("JSON saved to " + outputFilename);
}
});
};
Then in each JS containing ajax add these code in the head of JS file (it need to load before ajax)
var myURL;
$.getJSON("myURL.json", function(json) {
myURL = json.port.toString();
console.log(myURL);
});
new ajax format
$.ajax({
type: "POST",
url: myURL + "/forgetPwd",
data: sendData,
success: function(data){
window.location.replace(myURL);
},
error: function(data){
}
});
Finally, you can run server
node bin/www your_aws_ip
It works for me now. Hope these will help you guys.
By the way, you should be careful about the path of myURL.json.

NodeJS Redirecting WIth Single-Page JQuery Mobile

I'm working on a NodeJS/ExpressJS application using JQuery Mobile (JQM). I'm having trouble redirecting from the backend. My app dynamically generates buttons
<button class=\"setAttndingbtn btn btn-primary\" value=\"" + curr.place_id + "\">Attending: " + numAttending.numAttnd + " people are going</button>
after a $.getJSON search is made. Using promises/setTimeout, the following handler is attached to all buttons:
$('.setAttndingbtn').click(function(){
var buttonsir = $(this); //Store this button reference
if($(this).html().slice(0,1) == 'A'){ //Check the button's state
$.getJSON('/api/attending/' + $(this).val(), function(data){ //Ajax
$(buttonsir).text("You are attending! " + data.numAttnd + " people are going"); //Change state
});
} else {
$.getJSON('/api/attending/rmv/' + $(this).val(), function(data){
$(buttonsir).text("Attending: " + data.numAttnd + " people are going");
});
}
});
The relevant routes are here:
function isLoggedIn(req, res, next){
if(req.isAuthenticated()){
return next();
} else {
res.redirect('/login');
}
}
app.route('/login')
.get(function(req, res){
res.sendFile(p + "/public/login.html");
});
app.route('/api/attending/:number')
.get(isLoggedIn, searchServerInstance.setAttending);
On the backend, when an "Attending" button is clicked, I want to check if the user is logged in and if not, redirect them to the login page. When I run the code as is, in Firefox's Firebug console, I see the GET request and if I expand it, in the "Response" section, the HTML code to my login page is displayed. But the page doesn't actually load the file.
My /login.html has <div data-role="page">, header, and content tags, as JQM recommends. I've tried including the entire login page in my /index.html, but attempting to use res.redirect("/public/index.html#page2") results in a "file not found".
Is it possible to use Node/Express to tell JQM which <div data-role="page" id="page1"> to load? Is there a way to force JQM to load /login.html from the server-side, the way rel="external" allows for? Or will I have to ditch JQM?
Reading through the JQM documentation, I've figured out some ways to do this. For anyone else who encounters it, here's what I believe I understand:
If you don't care about maintaining the integrity of the single-page, you can look into turning off JQM's defaults, like ajaxEnabled, which turns off JQM's hash listening and ajax, loading URLs normally. I don't know if this works with Express's res.redirect because I haven't tried it.
What I opted to do was to replace res.redirect('/login.html') with a custom JSON response res.send({loginState: "LOGIN"}). Then, on the client side, within my $.getJSON request in the $('.setAttndngbtn') listener, i put the following code:
.
if(data.loginstate !== "LOGIN"){
$(buttonsir).text("You are attending! " + data.numAttnd + " people are going");
} else {
$(":mobile-pagecontainer").pagecontainer("change", '#page2');
}
And it works just fine! Here is the JQM documentation on the pagecontainer widget that allows in-page redirection with the change method or external redirection with the load method.

Resources