Delete files from SERVER through web interface - javascript

I need to create a web interface where users can upload files, view info about those (already stored) files and delete them. I've already written the first two parts (I use Node.js server), but I'm having serious problems with deleting stored files.
My main problem is, that I don't know, how to make a request with info about the file user want to delete correctly. I supposed that I will simply use open() method like this
xhr.open('POST', '/delete', true);
and then just "catch" it with condition in server code like this:
if (req.url == '/delete' && req.method.toLowerCase() == 'post') {th
But this solutions keeps throwing error 404 - Resource not found.
So, could you please help me and describe some way which works for you?
Here is my server code.
And this file contains client-side JavaScript.
- there is the problem in function createStoredFilesTable() in $('.deleteLink').click() block.

The solution was pretty simple in the end - the problem was missing "return" in the end of DELETE block, so the program handled the request and continued to loading source codes, where it couldn't find anything, because request URL was '/delete'.
So, the correct block of the server code is here:
//-------------------------------------------------------------------------------------
//--- DELETE handling ---//
//-----------------------//
if (req.url == '/delete' && req.method.toLowerCase() == 'post') {
req.on('data', function (data) {
var filename = data.toString('ascii');
var jsonObj = require('./storedFilesList.json');
delete jsonObj[filename];
var jsonString = JSON.stringify(jsonObj);
fs.writeFile('storedFilesList.json', jsonString, function(err){
if (err) throw err;
fs.unlinkSync(__dirname + '/uploadedFiles/' + filename);
console.log('File ' + filename + ' was succesfully deleted.');
});
res.writeHead(200, {'content-type': 'text/plain'});
res.write('OK');
res.end();
});
return;
}

Related

capture returned functions in javascript

I have the following piece of code as follows:
function(staticPath) {
console.log('static Path = ' +staticPath);
return function(data, response) {
console.log('data = ' +data);
console.log('response = ' +response);
var readStream;
// Fix so routes to /home and /home.html both work.
data = data.replace(/^(\/home)(.html)?$/i, '$1.html');
data = '.' + staticPath + data;
fs.stat(data, function(error, stats) {
if (error || stats.isDirectory()) {
return exports.send404(response);
}
readStream = fs.createReadStream(data);
return readStream.pipe(response);
});
}
}
This function basically parses the path to a HTML file and displays the contents of the file.
I am not able to understand how to call this method from outside.
I am calling it as follows:
staticFile("D:\\Node Applications\\public\\home.html")
I can capture it inside a variable innerFunc and i can call the inner function as innerFunc(response) where response is http's serverResponse of which i have the reference with me but i am not sure how can i pass the data param.
I am not understanding what is happening behind the scenes. Can anyone explain ? Do we encounter such kind of code often in javascript ?
EDIT:
To make things clear:
There is another method as follows:
function(data, response) {
response.writeHead(200, {
'Content-Type': 'application/json'
});
response.end(JSON.stringify(data));
}
which i call from my node server logic as follows:
http.createServer(function(req, res) {
// A parsed url to work with in case there are parameters
var _url;
// In case the client uses lower case for methods.
req.method = req.method.toUpperCase();
console.log(req.method + ' ' + req.url);
if (req.method !== 'GET') {
res.writeHead(501, {
'Content-Type': 'text/plain'
});
return res.end(req.method + ' is not implemented by this server.');
}
if (_url is something like //localhost:1337/employees) {
//call employee service which returns *data*.
// send the data with a 200 status code
return responder.sendJson(data, res);
});
} else {
// try to send the static file
/*res.writeHead(200);
res.end('static file maybe');*/
console.log('Inside else');
var staticInner = responder.staticFile("D:\\Node Applications\\public\\home.html");
staticInner(res);
}
// res.end('The current time is ' + Date.now())
}).listen(1337, '127.0.0.1');
As one can see there is no data variable to pass to the innerFunc hence, got confused.
According to the "innerFunc", it seems like data is some string that, being concatenated with staticPath, forms a path to a file. As we can see, that path is tested with fs.stat. Maybe the client is supposed to send some custom data? At any rate, data seems to be a pretty bad name for a variable like that.
It seems like what that function is trying to do is to send a file as response? What staticPath is supposed to be is a path relative to the Javascript file where this code is, because it is concatenated like this:
data = '.' + staticPath + data;
That would end in something like ./some/path/index.html. staticPath's value would be /some/path and data's value would be index.html. So if your JS file is in /home/foo/node/index.js, the file that the "innerFunc" will try to find would be in /home/foo/node/some/path/index.html.
If you pass "D:\\Node Applications\\public\\home.html" to staticFile() as you're doing, you would get something like .D:\\Node Applications\\public\\home.htmlindex.html which is clearly an invalid file.
To answer what's the point of a function returning a function
In this case, as mgouault said, it makes no sense at all to do that. Maybe the programmer had something in mind but changed it while programming this and the function ended up like that (it sometimes happen).
Your functions (ex: function(staticPath)) should either have a name or be stored in a variable to be able to call them. So I will guess that you are storing all this code in the variable staticFile.
Then when you call it with a parameter: staticFile("D:\\Node Applications\\public\\home.html") it returns a function (return function(data, response) {...}).
Now that you have this inner function you can call it with data and response:
var innerFunc = staticFile("D:\\Node Applications\\public\\home.html");
innerFunc(data, response);
Which will responds using your variable response (I guess).
A function returning a function is frequent in javascript especially when using closures for certains purposes, but in this case it's not really useful.

sock.js not allowing POST method for node server

Trying to bring up a node server that uses sock.js for websocket communication.
Can bring up the server fine and have established the websocket communication. However, we also need to POST to this instance with HTTP so that we can then send a message through the websocket. The message is dependent on the POST payload...
However, sock.js does not seem to be accepting the handler that we're creating, and is only allowing a GET method. This is causing a 405 HTTP code for any POSTs done to the server.
Please see following code. If I remove the sock.js implementation, I'm then able to process GET and POST requests with the server.
var app = require('http');
var sockjs = require('sockjs');
var sk = sockjs.createServer({ sockjs_url: '//cdn.jsdelivr.net/sockjs/1.0.1/sockjs.min.js' });
sk.on('connection', function (conn) {
console.log('connection' + conn);
conn.on('close', function () {
console.log('close ' + conn);
});
conn.on('data', function (message) {
console.log('message ' + conn,
message);
conn.write(message);
});
});
var server = app.createServer( function(req, res) {
if (req.method == 'POST') {
console.log("POST");
var body = '';
req.on('data', function (data) {
body += data;
console.log("Partial body: " + body);
});
req.on('end', function () {
console.log("Body: " + body);
});
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('post received');
}
else
{
console.log("GET");
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('get received');
}
});
sk.installHandlers(server);
I've tried different ways to set up the handlers, including following the example here; but regardless it just doesn't seem like I'm falling into my handlers but instead sock.js is not allowing POSTs.
If this is expected behavior from sock.js and is working the way it;s intended to, then recommendations for what to use would be appreciated. This is an attempt to move away from socket.io because that isn't working in all cases for us... but without being able to POST to the node server we probably won't be able to use sock.js either.
You're missing the prefix in your call to installHandlers. This results in sockjs handling all requests, rather than just those that are destined to it.
Just specify a prefix:
sk.installHandler(server,{prefix:"/whatever"});
It should of course match the prefix you use client-side.
Alternatively, if you don't want to use a prefix, use different ports.

Serving New Data With Node.js

There may already by an answer to this question but I was unable to find it.
Let's say I have a Node.js webpage doing somewhat time-consuming API calls and computations:
var request = require('request'),
Promise = require('es6-promise').Promise,
is_open = require('./is_open');
// Fetch the name of every eatery
var api_url = 'url of some api';
request(api_url, function (error, response, body) {
if (error) {
console.log(error);
} else if (!error && response.statusCode == 200) {
// Good to go!
var results = JSON.parse(body).events;
results.(function (result) {
// This line makes its own set of API calls
is_open(result
.then(function (output) {
console.log(output);
if (output == false) {
console.log('CLOSED\n');
} else {
console.log(output);
console.log();
}
})
.catch(console.error);
});
} else {
console.log('Returned an unknown error.');
console.log(error);
console.log(response);
console.log(body);
}
});
(I haven't yet created an actual web server, I'm just running the app locally through the command line.)
I want the web server to serve a loading page first to every user. Then, once the API calls are complete and the data is ready, it should send that data in a new webpage to the same user.
The reason I think there's an issue is because in order to serve a webpage, you must end with:
res.end();
Therefore ending the connection to that specific user.
Thanks for the help!
You must conceptually separate static content from dynamic content (later you will serve static with nginx or apache leaving only dynamic to node)
The best solution to your "problem" is to make the first webpage ask the data via AJAX once loaded. Ideally, your node app will return JSON to an ajax query from the first page, and js on the page will format the result creating DOM nodes.

JSONP call with server-side language as Javascript

I've been trying to use JSONP to get a JSON object from a server via a client-side call (on a different port). However, because my server is implemented in javascript using Node.js and Express, I haven't been able to find much on JSONP with Javascript on the server as most sites I found used php for server-side code.
I believe the issue is with how I set up the url with respect to the callback, which I'm a bit fuzzy on cause it's new to me.
On the server:
//Setting up server stuff
var express = require('express'),
app = express.createServer();
app.use(express.logger());
//Making a connection to the mongoDB to get the data that I want to display in the JSON object
new Db('prism',
new Server("127.0.0.1", 27017, {auto_reconnect: false}), {}).open(function(err, db) {
app.get('/getData', function(req, res) {
console.log('JSONPCALLBACK CALLED WITH RETURNDATA PASSED IN; SERVER SIDE');
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
}
});
And on the client:
$.ajaxSetup({ cache : false });
$.getJSON('http://127.0.0.1:1337/getData&callback=?', function(rtndata) {
console.log('SUCCESS');
console.log(rtndata);
});
embedded by the standard tags.
But I get the error:
GET http://127.0.0.1:1337/getData&callback=jQuery16108897686484269798_1311007334273?_=1311007334342 404 (Not Found)
The server is on port 1337 while the client is run through MAMP on localhost:8888. I'm not sure if its even a localhost related issue as I've been trying to get this setup running for a few days now.
I believe the issue has something to do with not writing this line, which is in php, into my server-side Javascript. Most of the JSONP examples I found had something like this. But I'm not sure.
if ($GET['callback'] != '')
$json = $GET['callback']."( $json )";
return $json;
Any help would be greatly appreciated. I apologize ahead of times for being super verbose.
Bests,
Cong
I think you have two problems. First is the 404. Completely separate from getting the client-side jQuery code to work, you need to make sure that you can issue a regular browser request (i.e. paste in that URL) and get back what you expect. I haven't used express, so it's hard for me to comment on why you'd be getting that, except to say that I don't see 1337 anywhere in your server-side code, just what appears to be the port number 27017.
The second problem is that you don't actually want to execute the callback on the server, just build the JSON response including the callback (string) prefixed to it.
So instead of this ...
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
try this:
if (callback) {
console.log('callback is defined');
res.write(callback + '(' + JSON.stringify(returnData) + ')');
}
else {
console.log('callback is not defined');
}
Hope this helps!
From http://api.jquery.com/jQuery.getJSON/ there is an example that includes 2 '?' in the URL.
you only have one, so try
$.getJSON('http://127.0.0.1:1337/getData?callback=?', function(rtndata) {
and see if that gets rid of your 404
then look #jimbojw suggestion for returning a proper jsonp formated responce.
Use this:
var express = require("express");
var server = express.createServer();
server.enable("jsonp callback");
server.get("/foo", function(req, res) {
// this is important - you must use Response.json()
res.json("hello");
});
jsonp with node.js express

Basic Ajax send/receive with node.js

So I'm trying to make a very basic node.js server that with take in a request for a string, randomly select one from an array and return the selected string. Unfortunately I'm running into a few problems.
Here's the front end:
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","server.js", true);
xmlhttp.send();
string=xmlhttp.responseText;
}
This should send the request to server.js:
var http = require('http');
var choices=["hello world", "goodbye world"];
console.log("server initialized");
http.createServer(function(request, response)
{
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.on(string);
console.log("string sent");
}).listen(8001);
So clearly there are several things going wrong here:
I get the feeling the way I am "connecting" these two files isn't correct both in the xmlhttp.open method and in using response.on to send the string back to the front end.
I'm a little confused with how I call this page on localhost. The front end is named index.html and the sever posts to 8001. What address should I be go to on localhost in order to access the initial html page after I have initialized server.js? Should I change it to .listen(index.html) or something like that?
are there other obvious problems with how I am implementing this (using .responsetext etc.)
(sorry for the long multi-question post but the various tutorials and the node.js source all assume that the user already has an understanding of these things.)
Your request should be to the server, NOT the server.js file which instantiates it. So, the request should look something like this: xmlhttp.open("GET","http://localhost:8001/", true); Also, you are trying to serve the front-end (index.html) AND serve AJAX requests at the same URI. To accomplish this, you are going to have to introduce logic to your server.js that will differentiate between your AJAX requests and a normal http access request. To do this, you'll want to either introduce GET/POST data (i.e. call http://localhost:8001/?getstring=true) or use a different path for your AJAX requests (i.e. call http://localhost:8001/getstring). On the server end then, you'll need to examine the request object to determine what to write on the response. For the latter option, you need to use the 'url' module to parse the request.
You are correctly calling listen() but incorrectly writing the response. First of all, if you wish to serve index.html when navigating to http://localhost:8001/, you need to write the contents of the file to the response using response.write() or response.end(). First, you need to include fs=require('fs') to get access to the filesystem. Then, you need to actually serve the file.
XMLHttpRequest needs a callback function specified if you use it asynchronously (third parameter = true, as you have done) AND want to do something with the response. The way you have it now, string will be undefined (or perhaps null), because that line will execute before the AJAX request is complete (i.e. the responseText is still empty). If you use it synchronously (third parameter = false), you can write inline code as you have done. This is not recommended as it locks the browser during the request. Asynchronous operation is usually used with the onreadystatechange function, which can handle the response once it is complete. You need to learn the basics of XMLHttpRequest. Start here.
Here is a simple implementation that incorporates all of the above:
server.js:
var http = require('http'),
fs = require('fs'),
url = require('url'),
choices = ["hello world", "goodbye world"];
http.createServer(function(request, response){
var path = url.parse(request.url).pathname;
if(path=="/getstring"){
console.log("request recieved");
var string = choices[Math.floor(Math.random()*choices.length)];
console.log("string '" + string + "' chosen");
response.writeHead(200, {"Content-Type": "text/plain"});
response.end(string);
console.log("string sent");
}else{
fs.readFile('./index.html', function(err, file) {
if(err) {
// write an error response or nothing here
return;
}
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end(file, "utf-8");
});
}
}).listen(8001);
console.log("server initialized");
frontend (part of index.html):
function newGame()
{
guessCnt=0;
guess="";
server();
displayHash();
displayGuessStr();
displayGuessCnt();
}
function server()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET","http://localhost:8001/getstring", true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
string=xmlhttp.responseText;
}
}
xmlhttp.send();
}
You will need to be comfortable with AJAX. Use the mozilla learning center to learn about XMLHttpRequest. After you can use the basic XHR object, you will most likely want to use a good AJAX library instead of manually writing cross-browser AJAX requests (for example, in IE you'll need to use an ActiveXObject instead of XHR). The AJAX in jQuery is excellent, but if you don't need everything else jQuery offers, find a good AJAX library here: http://microjs.com/. You will also need to get comfy with the node.js docs, found here. Search http://google.com for some good node.js server and static file server tutorials. http://nodetuts.com is a good place to start.
UPDATE: I have changed response.sendHeader() to the new response.writeHead() in the code above !!!
Express makes this kind of stuff really intuitive. The syntax looks like below :
var app = require('express').createServer();
app.get("/string", function(req, res) {
var strings = ["rad", "bla", "ska"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
})
app.listen(8001)
https://expressjs.com
If you're using jQuery on the client side you can do something like this:
$.get("/string", function(string) {
alert(string)
})
I was facing following error with code (nodejs 0.10.13), provided by ampersand:
origin is not allowed by access-control-allow-origin
Issue was resolved changing
response.writeHead(200, {"Content-Type": "text/plain"});
to
response.writeHead(200, {
'Content-Type': 'text/html',
'Access-Control-Allow-Origin' : '*'});
Here is a fully functional example of what you are trying to accomplish. I created the example inside of hyperdev rather than jsFiddle so that you could see the server-side and client-side code.
View Code:
https://hyperdev.com/#!/project/destiny-authorization
View Working Application: https://destiny-authorization.hyperdev.space/
This code creates a handler for a get request that returns a random string:
app.get("/string", function(req, res) {
var strings = ["string1", "string2", "string3"]
var n = Math.floor(Math.random() * strings.length)
res.send(strings[n])
});
This jQuery code then makes the ajax request and receives the random string from the server.
$.get("/string", function(string) {
$('#txtString').val(string);
});
Note that this example is based on code from Jamund Ferguson's answer so if you find this useful be sure to upvote him as well. I just thought this example would help you to see how everything fits together.

Categories

Resources