detect ajax request to normal request node js - javascript

hello h have the next code and i like to know how to detect between an ajax request to a normal request? without express.
var http = require('http');
var fs = require('fs');
var path = require('path');
var url = require('url');
http.createServer(function (request, response) {
console.log('request starting...');
console.log("request.url = " + request.url);
console.log("url = "+ url);
response.setHeader('content-Type','application/json');
var filePath = '.' + request.url;
if (filePath == './')
filePath = './index.html';
var extname = path.extname(filePath);
var contentType = 'text/html';
switch (extname)
{
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
}
fs.exists(filePath, function(exists) {
if (exists)
{
fs.readFile(filePath, function(error, content) {
if (error)
{
response.writeHead(500);
response.end();
}
else
{
console.log("contentType = "+contentType);
response.writeHead(200, { 'content-Type': contentType });
response.end(content, 'utf-8');
}
});
}
else
{
response.writeHead(404);
response.end();
}
});
}).listen(8081);
console.log('Server running at http://localhost:8081/');
in the client side i send an ajax request but i ask from the browser request to.

You can check request.headers if it contains HTTP_X_REQUESTED_WITH.
If HTTP_X_REQUESTED_WITH has a value of XMLHttpRequest then it is an ajax request.
Example:
if (request.headers["x-requested-with"] == 'XMLHttpRequest') {
//is ajax request
}

I came across this question and I know it's old but in case someone needs the answer and the idea behind it.
Usually, on the client side, when you make an AJAX request you add a key and value that describe the content i.e: 'content type':'application/json'
So simply, on the server side, you can test the header if it contains application/json as the content type then you are safe to say it's an ajax request.
req.headers['content-type'] == 'application/json'

Related

memory error in node JS (node::smalloc::Alloc)

I'm new to node Js, I've build a really simple server that send me back a zip file I request. It's all working but after some request a crash occur and i visualize this message on the terminal :
FATAL ERROR: node::smalloc::Alloc(v8::Handle, size_t, v8::ExternalArrayType) Out Of Memory
var http = require('http');
var url = require('url');
var fs = require('fs');
var port = 1337;
// create http server
var server = http.createServer(function (request, response) {
var path = require('url').parse(request.url, true);
console.log('requested ' + path.pathname);
//get zipped resoures
if (path.pathname == '/getzip') {
console.log(request.url);
var queryData = url.parse(request.url, true).query;
if (queryData.name) {
var filename = queryData.name;
//open corrisponding file
var zipFile = fs.readFileSync('packets/' + filename);
response.writeHead(200, {
'Content-Type': 'application/x-zip',
'Content-disposition': 'attachment; filename=data.zip'
});
//send file in response
response.end(zipFile);
}
else {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('{error = "bad url"}');
}
}
}).listen(port);
server.timeout = 1000000;
Do you have any idea of what it can be? this code looks so simple.
Instead of reading the entire file into memory, you should leverage streams for this:
response.writeHead(200, {
'Content-Type' : 'application/x-zip',
'Content-disposition' : 'attachment; filename=data.zip'
});
fs.createReadStream('packets/' + filename).pipe(response);

Node.js HTTP WebServer Write after End error

I am new to node.js and have been trying to setup just a basic server to start with.
I have the code below running and I get a "Write After End" error.
Socket.html is a basic html file that has a hello world string in the body. There is literally nothing else in that file. I have tried using the "ReadFileSync" method and that throws up a whole new set of errors that I don't fully understand.
I will appreciate any help on this. I am brand new to this so please go a little easy on me :) Thank you in advance!
I have verified that the path is correct, and that the buffer does have the data.
var http = require('http');
var url = require('url');
var fs = require('fs');
var server = http.createServer(function(request, response){
console.log('Connection');
var path = url.parse(request.url).pathname.substr(1);
path = "\\" + path;
switch(path){
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
break;
case '\\socket.html':
//console.log(path);
fs.readFile(__dirname + path, function(error, data){
if(error){
response.writeHead(404);
response.write("This domain is missing");
}
else{
console.log(data);
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data,"utf8");
}
});
break;
default:
response.writeHead(404);
response.write("This domain is missing");
break;
}
response.end();
});
server.listen(8001);
I think when you read from the FileSystem async, the response.end() method is called before response.write() I would suggest using the following code instead:
var http = require('http');
var url = require('url');
var fs = require('fs');
var server = http.createServer(function(request, response) {
var path = url.parse(request.url).pathname.substr(1);
path = "\\" + path;
switch(path) {
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
response.end();
break;
case '\\socket.html':
fs.readFile(__dirname + path, function(error, data) {
if(error) {
response.writeHead(404);
response.write("This domain is missing");
} else {
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
}
response.end();
});
break;
default:
response.writeHead(404);
response.write("This domain is missing");
response.end();
break;
}
});

node.js redirection not working to add username

I am working on a Team Treehouse project that builds a dynamic website with Node.js. The user enters in a username into the search field and it displays the user's avatar, number of badges earned and the number of JavaScript points. For some reason when I enter in the user name and click search the page just goes blank. I think there might be something wrong with the 303 redirection in my router.js file. I'm still fairly new to coding so any insight would be very helpful. Here are each of my js files.
/*****app.js file******/
var router = require('./router.js');
//Problem: We need a simple way to look at a user's badge count and JavaScript points from a web browser
//Solution: Use Node.js to perform the profile look ups and serve our templates via HTTP
//Create a web server
var http = require('http');
http.createServer(function (request, response) {
router.home(request, response);
router.user(request, response);
}).listen(3000);
console.log('Server running at http://<workspace-url>');
/*****router.js file******/
var Profile = require("./profile.js");
var renderer = require('./renderer');
var querystring = require('querystring');
var commonHeader = {'Content-Type': 'text/html'};
// Handle the HTTP route GET / and POST / i.e. Home
function home(request, response) {
//if url == "/" && GET
if (request.url === '/'){
if (request.method.toLowerCase() === "get") {
//show search
console.log(request.url);
response.writeHead(200, commonHeader);
renderer.view('header', {}, response);
renderer.view('search', {}, response);
renderer.view('footer', {}, response);
response.end();
}
else {
//if url == "/" && POST
//get the post data from body
request.on('data', function(postBody){
//extract the username
var query = querystring.parse(postBody.toString());
//redirect to /:username
response.writeHead(303, {'Location': '/' + query.username });
response.end();
});
}
}
}
// Handle the HTTP route for GET /:username i.e. /chalkers
function user(request, response) {
//if url == "/...."
var username = request.url.replace('/', '');
if(user.name.length > 0){
response.writeHead(200, commonHeader);
renderer.view('header', {}, response);
//get json from Treehouse
var studentProfile = new Profile(username);
//on "end"
studentProfile.on("end", function(profileJSON){
//show profile
//Store the values which we need
var values = {
avatarUrl: profileJSON.gravatar_url,
username: profileJSON.profile_name,
badges: profileJSON.badges.length,
javascriptPoints: profileJSON.points.JavaScript
}
//Simple response
renderer.view('profile', values, response);
renderer.view('footer', {}, response);
response.end();
});
//on "error"
studentProfile.on("error", function(error){
//show error
renderer.view('error', {errorMessage: error.message}, response);
renderer.view('search', {}, response);
renderer.view('footer', {}, response);
response.end();
});
}
}
module.exports.home = home;
module.exports.user = user;
/*****profile.js file*******/
var EventEmitter = require("events").EventEmitter;
var http = require("http");
var util = require("util");
/**
* An EventEmitter to get a Treehouse students profile.
* #param username
* #constructor
*/
function Profile(username) {
EventEmitter.call(this);
profileEmitter = this;
//Connect to the API URL (http://teamtreehouse.com/username.json)
var request = http.get("http://teamtreehouse.com/" + username + ".json", function(response) {
var body = "";
if (response.statusCode !== 200) {
request.abort();
//Status Code Error
profileEmitter.emit("error", new Error("There was an error getting the profile for " + username + ". (" + http.STATUS_CODES[response.statusCode] + ")"));
}
//Read the data
response.on('data', function (chunk) {
body += chunk;
profileEmitter.emit("data", chunk);
});
response.on('end', function () {
if(response.statusCode === 200) {
try {
//Parse the data
var profile = JSON.parse(body);
profileEmitter.emit("end", profile);
} catch (error) {
profileEmitter.emit("error", error);
}
}
}).on("error", function(error){
profileEmitter.emit("error", error);
});
});
}
util.inherits( Profile, EventEmitter );
module.exports = Profile;
/*****renderer.js file*******/
var fs = require('fs');
function mergeValues(values, content) {
//Cycle over the keys
for(var key in values) {
//Replace all the {{key}} with the value from the values object
content = content.replace('{{' + key + '}}', values[key]);
}
//return merged content
return content;
}
function view(templateName, values, response) {
//Read from the template file
var fileContents = fs.readFileSync('./views/' + templateName + '.html', {encoding: 'utf8'});
//Insert values in to the content
fileContents = mergeValues(values, fileContents);
//Write out the contents to the response
response.write(fileContents);
}
module.exports.view = view;
Treehouse changed from http to https and so this example code doesn't work any longer. The reason for that is in the profile.js file. You are making calls for an http site and it doesn't exist. You need to change the code (only in profile.js) to make it connect to the https site instead.
var http = require("http");
should be changed to
var https = require("https");
and with that all references to the variable in your profile.js code should be changed to https.
As well as the hard-coded URL start:
var request = http.get("http://teamtreehous...
should be
var request = https.get("https://teamtreehous...
That should resolve the problem. Good luck!
In order to get your code in the profile.js file to run, you need to change some instances of the "http" module to "https" but, and this is important, not all instances.
What needs to remain http is the the status code error on the profile.js page. This line of code is correct:
profileEmitter.emit("error", new Error("There was an error getting the profile for " + username + ". (" + http.STATUS_CODES[response.statusCode] + ")"));
But all other instances of the http module need to change to https. For example, these lines are correct:
var url = "https://teamtreehouse.com/" + username + ".json";
var request = https.get(url, function(response){
Remember to require both modules at the top of profile.js page
var http = require("http");
var https = require("https");

Static HTTP File Server in NodeJs: Sometimes external .js and .css files load properly, sometimes they don't?

Edit: I know using express or whatever would be easier, but this is all a learning exercise, so sorry if this is all massively convoluted, haha!
Edit 2: It appears (after adding a few console logs for debugging) that it seems the problem has something to do with the fact that when the browser makes one request to the server (say, for style.css), it makes another request (e.g. for login-fail.js) before completing the response for the first request. It seems these multiple requests from the browser cause some sort of problem, each subsequent request preventing the previous from completing. Yikes, I need help.
Edit 3: After some debugging, it appears that the pathname variable does not change its value upon each request. For some reason, pathname's value persists over each request and this makes every request's response the same - stranger still, the value for uri changes over each request (and the uri is what gives the pathname its value...) still trying to find out why this bizarre behaviour is happening.
So I've been having this problem when the server makes requests for external .js and .css files linked to specific .html files. The responses are always inconsistent. For instance, sometimes the code will run perfectly, other times the css will load and not the js, sometimes both, sometimes neither. I am not able to determine whether this is because my code is synchronous, or for some other reason. Here is my code:
Server.js
//Module requires
var http = require("http"),
fs = require("fs"),
path = require('path'),
url = require('url'),
invoke = require("./invoke");
//Object "MIMETYPES"
//Maps relationships between file extensions and their respective MIME Content-Types
var MIMETYPES = {
".html": "text/html",
".jpeg": "image/jpeg",
".jpg": "image/jpeg",
".png": "image/png",
".js": "text/javascript",
".css": "text/css"
};
//Object "invokeOptions"
//Options passed to Invoke() function for POST requests
var invokeOptions = {
postData : "",
uri : ""
}
var PORT = 8888;
//HTTP Server Begin
http.createServer(function(req, res) {
var uri = url.parse(req.url).pathname;
pathname = path.resolve(__dirname, "..") + uri;
console.log("Recieved " + req.method + " request for : " + uri);
invokeOptions.uri = uri;
//GET requests wrapper
if (req.method == "GET"){
//Invoke() function handler for GET requests
if (path.extname(pathname) == ""){
invoke.invoke(invokeOptions, req, res);
return;
}
//Static file server for GET requests
fs.exists(pathname, function(exists) {
if(!exists) {
console.log("Requested file \'" + pathname + "\' doesn't exist.");
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('404 Not Found\n');
res.end();
return;
}
var contentType = MIMETYPES[path.extname(pathname)];
res.writeHead(200, {"Content-Type" : contentType});
console.log("Current URI: " + uri + " has content type: " + contentType);
fs.createReadStream(pathname).pipe(res);
return;
});
}
//POST requests wrapper
if (req.method == "POST"){
var postData = "";
req.on("data", function(postPacket) {
postData += postPacket;
});
req.on("end", function() {
invokeOptions.postData = postData;
invoke.invoke(invokeOptions, req, res);
return;
});
}
}).listen(PORT);
console.log ("Server listening on port: " + PORT);
Invoke.js - This handles requests for non-files, that is requests for functions on the server
var fs = require("fs"),
querystring = require("querystring"),
path = require("path");
function invoke (options, req, res){
process.stdout.write("Invoking function --> ");
if (options.uri == "/"){
console.log("Index");
res.writeHead(200, {"Content-Type" : "text/html"});
fs.createReadStream("../index.html").pipe(res);
return;
}
if (options.uri == "/login"){
console.log("Login");
fs.readFile(path.resolve("../users.json"), "UTF-8", function(err, data){
if (err) throw err;
var json = JSON.parse(data);
var user = querystring.parse(options.postData).username,
password = querystring.parse(options.postData).password;
console.log("Submitted Username: " + user + "\nSubmitted Password: " + password);
if (json.users[0].username == user && json.users[0].password == password){
res.writeHead(200, {"Content-Type" : "text/html"});
fs.createReadStream("../app.html").pipe(res);
return;
}
else {
res.writeHead(300, {"Content-Type" : "text/html"});
fs.createReadStream("../login-fail.html").pipe(res);
return;
}
});
}
else {
console.log("Error! Bad request.");
res.writeHead(400, {"Content-Type" : "text/plain"});
res.end("Error 400: Bad Request. \nThere is no function corresponding to that request.");
}
}
exports.invoke = invoke;
Login-fail.js - This is the code that hardly ever loads
$(document).ready(function() {
var current = 3;
var countdown = $(".countdown");
function down (){
current--;
if (current != 0){
countdown.text(current);
}
else {
clearInterval(interval);
window.location.replace("./");
}
}
var interval = setInterval(down, 1000);
});
Basically, the index.html file is a form which accepts a username and password, compares the submitted POST data to a json file, and if it matches the hashes in the json file it requests app.html, otherwise it requests login-fail.html. When the login-html file is called, it has linked to it css and js which when requested hardly ever run!
Also, I thought it should be noted that the console.logs for "content-type" when requesting the css is 'text/javascript' when it doesn't work. Any help would be massively appreciated!
Holy crap.
Pathname wasn't being declared as a variable each request, because I used a ; instead of a ,
I'll go die now ladies and gents.
The relative paths you're using in your login-fail.html are probably not resolving correctly because the URL path doesn't change (/login), so the browser is looking for /login/css/style.css and /login/js/login-fail.js. Try modifying your login-fail.html to use absolute paths instead of relative paths.

Problem receiving response from node server using ajax post request

I have written a http server using node js
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
http.createServer(function(request, res) {
var parsed_url = url.parse(request.url);
var uri = parsed_url.pathname;
if(uri === "/test"){
res.writeHead(200, {'Content-Type': 'text/javascript'});
request.addListener('data', function (chunk) {
var data = eval("(" + chunk + ")");
console.log(data[0].id);
})
request.addListener('end', function() {
console.log('end triggered');
res.write("Post data");
res.end();
});
}
}).listen(8080);
and i am trying to send back response of ajax request but i am unable to receive any response. Here is the code for ajax request ,
var myhttp = new XMLHttpRequest();
var url = "http://localhost:8080/test";
var data = [{"a":"1"},{"b":"2"},{"c":"3"}];
var dataJson = JSON.stringify(data);
myhttp.open('POST', url, true);
myhttp.send(dataJson);
myhttp.onreadystatechange = function() {
if ((myhttp.readyState == 4) && (myhttp.status == 200)){
alert(myhttp.responseText);
}
else if ((myhttp.readyState == 4) && (myhttp.status != 200))
{
console.log("Error in Connection");
}
Can anyone help me what i am doing wrong ...
Thanks
Vinay
Your code is almost right but on your code sample you have
console.log(data[0].id)
the data object has no property id so if you only have
console.log(data[0])
there you have a response like
{ a: '1' }
therefore you can access the property a by doing
console.log(data[0].a);
UPDATED Updated with a full example
One more thing is that you are using eval and node comes with JSON.parse bundle with it so the snippet below is how i made it work
File: app.js
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
http.createServer(function(request, res) {
var parsed_url = url.parse(request.url);
var uri = parsed_url.pathname;
if(uri === "/test"){
res.writeHead(200, {'Content-Type': 'text/javascript'});
request.addListener('data', function (chunk) {
// removed this - eval("(" + chunk + ")");
var data = JSON.parse(chunk);
console.log(data[0].a);
})
request.addListener('end', function() {
console.log('end triggered');
res.write("Post data");
res.end();
});
} else if(uri === "/") {
fs.readFile("./index.html",function(err, data){
if(err) throw err;
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data);
});
}
}).listen(8080);
On the same directory create a file index.html with the following:
<html>
<head>
<script type="text/javascript" charset="utf-8">
var myhttp = new XMLHttpRequest();
var url = "http://localhost:8080/test";
var data = [{"a":"1"},{"b":"2"},{"c":"3"}];
var dataJson = JSON.stringify(data);
myhttp.open('POST', url, true);
myhttp.send(dataJson);
myhttp.onreadystatechange = function() {
if ((myhttp.readyState == 4) && (myhttp.status == 200)){
alert(myhttp.responseText);
}
else if ((myhttp.readyState == 4) && (myhttp.status != 200))
{
console.log("Error in Connection");
}
}
</script>
</head>
<body>
</body>
</html>
That is a complete working example of what you want.
With regards to the same origin policy issues you were having is mainly due to the fact that you cant POST data between 2 different domains via ajax unless you use some tricks with iframes but that is another story.
Also i think is good for anyone to understand the backbone of a technology before moving into frameworks so fair play to you.
good luck
You have to read the data in a different way. Posted data arrives on a node server in chunks (the 'data' event), that have to be collected until the 'end' event fires. Inside this event, you are able to access your payload.
var body = '';
request.addListener('data', function (chunk) {
body += chunk;
});
request.addListener('end', function() {
console.log(body);
res.write('post data: ' + body);
});
Additionaly, there seem to be some issues with your client-side code (especially concerning the status-code checks), but i can't really help you with those as i always work with frameworks like jQuery to manage async requests.
If you want to build reliable node.js servers for web use, i highly recommend the high-performance HTTP-Framework Express. It takes away alot of the pain when developing a web-based server application in node and is maintained actively.

Categories