Parsing Unexpected End - javascript

Can someone please explain me why I am getting an issue with this one line because for some reason when I run it with node in the console I'm receiving the Unexpected end of input at Object.parse(native) response.
var profile = JSON.parse(body);
Full code:
//Problem: We need a simple way to look at a user's badge count and Javascript points
//Solution: Use Node.js to connect to Treehouse's API to get profile information to print out
var http = require("http");
var username = "testuser";
//Print out message
function printMessage(username, badgeCount, points) {
var message = username + " has " + badgeCount + " total badge(s) and " + points + " points in Javascript";
console.log(message);
}
//Print out error messages
function printError(error) {
console.error(error.message);
}
//Connect to API URL (http://teamtreehouse.com/username.json)
var request = http.get("http://teamtreehouse.com/" + username + ".json", function(response) {
var body = "";
//Read the data
response.on('data', function(chunk) {
body += chunk;
});
response.on('end', function() {
if(response.statusCode == 200){
try {
var profile = JSON.parse(body);
printMessage(username, profile.badges.length, profile.points.Javascript);
} catch(error) {
//Parse Error
printError(error);
}
} else {
//Status Code Error
printError({message: "There was an error getting the profile for " + username +". (" + http.SSTATUS_CODES[response.statusCode] + ")"});
}
});
//Parse the data
//Print the data
});
//Connection Error
request.on('error', printError);

When I try to browse to http://teamtreehouse.com/test.json, it redirects me to the corresponding HTTPS url. Use the nodejs https module and use the https version of the url : https://teamtreehouse.com/test.json.
Or use the popular request module that can handle redirects and https : https://github.com/request/request. It is easier to use as well.

Related

How to use node modules correctly

I am a CS student with a strong Java background, and javascript is resulting to be a challenging but fun experience so far, that is until I ran into the situation where I tried to use my own modules to return values that require the program to wait for the completion of some procedure before returning.So far no-one from any forum that I have posted this question on has been able to give an actual code fix to the problem, they have referred me to read further material that is not related to the problem at hand. Would anyone please read the code and provide a working correct standard solution to the problem I am facing?
Here is the code, a simple nodes server application, app.js and a weather module, weatherApp.js that uses an user provided zip code and returns a weather forecast in the area.
here is the code:
weatherApp.js
// The required modules.
var http = require("http");
var https = require("https");
//result object
var resultSet = {
googleRequestUrl:"",
forecastIOrequest:"",
latitude :"",
longitude:"",
localInfo:"",
weather:"",
humidity:"",
pressure:"",
time:""
};
//print out error messages
function printError(error){
console.error(error.message);
}
//Forecast API required information:
//key for the forecast IO app
var forecast_IO_Key = "bb9aac7c57877f8f5fab339e3b55669a";
var forecast_IO_Web_Adress = "https://api.forecast.io/forecast/";
//Create Forecast request string function
function createForecastRequest(latitude, longitude){
var request = forecast_IO_Web_Adress + forecast_IO_Key + "/"
+ latitude +"," + longitude;
return request;
}
//Google GEO API required information:
//Create Google Geo Request
var google_GEO_Web_Adress = "https://maps.googleapis.com/maps/api/geocode/json?address=";
function createGoogleGeoMapRequest(zipCode){
var request = google_GEO_Web_Adress+zipCode + "&sensor=false";
return request;
}
// 1- Need to request google for geo locations using a given zip
function connectToGoogleGEO(zipCode, afterCallback){
var googleRequest = https.get(createGoogleGeoMapRequest(zipCode), function(response){
//saving the Google request URL
resultSet.googleRequestUrl = createGoogleGeoMapRequest(zipCode);
var body = "";
var status = response.statusCode;
//a- Read the data.
response.on("data", function(chunk){
body+=chunk;
});
//b- Parse the data.
response.on("end", function(){
if(status === 200){
try{
var googleReport = JSON.parse(body);
resultSet.latitude = googleReport.results[0].geometry.location.lat;
resultSet.longitude = googleReport.results[0].geometry.location.lng;
resultSet.localInfo = googleReport.results[0].address_components[0].long_name + ", " +
googleReport.results[0].address_components[1].long_name + ", " +
googleReport.results[0].address_components[2].long_name + ", " +
googleReport.results[0].address_components[3].long_name + ". ";
// callback to forecast IO.
afterCallback(resultSet.latitude, resultSet.longitude);
}catch(error){
printError(error.message);
}finally{
// nothing here
}
}else{
printError({message: "Error with GEO API"+http.STATUS_CODES[response.statusCode]})
}
});
});
}
function connectToForecastIO(latitude,longitude){
var forecastRequest = https.get(createForecastRequest(latitude,longitude),function(response){
resultSet.forecastIOrequest = createForecastRequest(latitude,longitude);
var body = "";
var status = response.statusCode;
//read the data
response.on("data", function(chunk){
body+=chunk;
});
//parse the data
response.on("end", function(){
try{
var weatherReport = JSON.parse(body);
resultSet.weather = weatherReport.currently.summary;
resultSet.humidity = weatherReport.currently.humidity;
resultSet.temperature = weatherReport.currently.temperature;
resultSet.pressure = weatherReport.currently.pressure;
resultSet.time = weatherReport.currently.time;
}catch(error){
printError(error.message);
}finally{
console.log(resultSet);
}
});
});
}
function get(zipCode){
var results = connectToGoogleGEO(zipCode, connectToForecastIO);
return results;
}
//define the name of the outer module.
module.exports.get = get;
And here is the server code:
app.js
var express = require("express");
var weatherApp = require("./weatherApp.js");
var path = require("path");
var http = require("http");
var app = express();
//creating routes
//The home
app.get("/", function(req, res){
res.redirect("/weather");
});
app.get("/weather", function(req, res){
res.sendFile(path.join(__dirname + "/index.html"));
});
//------------------------------------------------------
//The resources, css, web js files, images etc.
app.get("/StyleSheets/style.css", function(req, res){
res.sendFile(path.join(__dirname + "/StyleSheets/style.css"));
});
app.get("/webScripts/app.js", function(req, res){
res.sendFile(path.join(__dirname + "/webScripts/app.js"));
});
app.get("/webImages/swirl_pattern.png", function(req, res){
res.sendFile(path.join(__dirname + "/webImages/swirl_pattern.png"));
});
//-------------------------------------------------------
//other requests
app.get("/zipcode.do", function(req, res){
var zipcode = req.query["zipcode"];
var response = "No report Available";
function getReport(zipCode, callback){
response = weatherApp.get(req.query["zipcode"]);
}
getReport(zipcode, ()=>{
res.send("<p>" + response+ "</p>");
});
});
//any other entry thats not listed as a valid to request
app.get("/:title", function(req,res){
var title = req.param.title;
if(title === undefined){
var status = res.status(503);
res.send("This page does not exists" + '"' + http.STATUS_CODES[503] + '"');
}else{
res.send(title);
}
});
app.listen(3000, function(){
console.log("Server running at port: 3000")
});
The main issue I am having right now is:
The program is not returning anything from the module even when final console.log in the weather module prints the right resultSet object.
The server is not waiting for the module to return, and continues to print no data.
Can someone provide a working fix to any of these problems I would be really grateful, This has really hindered my progress and broken down my morale a little :(
Your problem is that you are using asynchronous functions as if they were synchronous.
It might not be the only issue here, but this function is particularly problematic:
function get(zipCode){
var results = connectToGoogleGEO(zipCode, connectToForecastIO);
return results;
}
connectToGoogleGEO() calls the asynchronous https.get() function and does not return the data that is retrieved from Google. You need to rewrite your code so that it does not expect the data to be returned by the function. Instead, you need to pass a callback that will handle the data.
Take care to know when you are calling asynchronous functions and how their callbacks work. It is fundamental when working with Node.js

invalid_request from getToken in Javascript from Node.js

I have the following code in a node.js server application
app.get('/AuthorizeGoogle.html',function(req,res) {
var auth = new googleapis.OAuth2Client(config.google_login.client_id, config.google_login.client_secret, config.google_login.redirect_uri);
var queryData = url.parse(req.url,true).query;
var code = encodeURIComponent(queryData.code);
console.log('Authorization Request recieved ');;
console.log('Retrieiving token');
auth.getToken(code,function(err,tokens) {
console.log('Retrievied token ');
console.log(tokens);
console.log('**** ERROR ****');
console.log(err);
console.log('Calling setCredentials');
auth.setCredentials(tokens);
console.log('*****FINISHED!!!!!');
});
res.send('Authorization recieved ' + queryData.code)
});
This is called when Google returns and the user has authorised access to their Google account.
I get a code. However when auth.getToken() I am getting invalid_request. I have done this successfully in C#, but I am now moving to more open source tools hence moving the project to Node.js
Thanks in advance
OK - I looked again at the page suggested and did some refactoring of my code and that worked. I think what may have been the problem was the Url used to get the token in the first place.
I was already initialising the oauth2Client
var OAuth2Client = googleapis.OAuth2Client;
var oauth2Client;
oauth2Client = new OAuth2Client(config.google_login.client_id, config.google_login.client_secret, config.google_login.redirect_uri);
The required Client Id, secret and redirect Url have been defined in a configuration file
So first all I changed the way I was generating that url. First off I set the Url to Login to Google to GoogleLogin.html which executes the following when the server receives a request for this page.
app.get('/GoogleLogin.html',function(req,res) {
var scopes = "";
// retrieve google scopes
scopes += config.google_login.scopes.baseFeeds + " "
scopes += config.google_login.scopes.calendar + " "
scopes += config.google_login.scopes.drive + " "
scopes += config.google_login.scopes.driveMetadata + " "
scopes += config.google_login.scopes.profile + " "
scopes += config.google_login.scopes.email + " "
scopes += config.google_login.scopes.tasks
var url = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: scopes
});
res.writeHead(302, {location: url});
res.end();
});
This first building a string of the scopes then generating the Authorization Url before redirecting to the generated url
When Google redirects back to the site the following is executed
app.get('/AuthorizeGoogle.html',function(req,res) {
// var auth = new googleapis.OAuth2Client(config.google_login.client_id,config.google_login.client_secret, config.google_login.redirect_uri);
var queryData = url.parse(req.url,true).query;
var code = queryData.code;
console.log('Authorization Request recieved ');;
console.log('Retrieving token');
oauth2Client.getToken(code,function(err,tokens) {
console.log('Retrieved token ');
console.log(tokens);
console.log('**** ERROR ****');
console.log(err);
console.log('Calling setCredentials');
oauth2Client.setCredentials(tokens);
console.log('*****FINISHED!!!!!');
});
res.send('Authorization recieved ' + queryData.code)
});
And this is now returning the Token and Refresh token correctly. Since it is the same code the only thing I can was wrong was the original call to Google.
I think your best bet would be to research what is done in the following github example: https://github.com/google/google-api-nodejs-client/blob/master/examples/oauth2.js

Meteor.http.get request -> Error: Hostname/IP doesn't match certificate's altnames

I'm trying to use meteor.http module and I'm getting the following error on the server side.
"Error: Hostname/IP doesn't match certificate's altnames" since I'm new in Meteor and in Node.js and its javaScript debugging is hard (btw how can I debug server side scripts ? client side it's easy), I'm using MAC OS X 10.9 not sure if it's relevent...
Thanks
Ronen
client side code:
'click #buildButton' : function () {
console.log("Jenkins job request");
$('#buildButton').attr('disabled','true').val('loading...');
var userName = "Ronen";
Meteor.call('jenkinsServiceBuild', function(err, respJson) {
if(err) {
window.alert("Error: " + err.reason);
console.log("error occured on receiving data on server. ", err );
} else {
window.alert("Success: ");
console.log("respJson: ", respJson);
//window.alert(respJson.length + ' tweets received.');
Session.set("recentTweets",respJson);
}
$('#buildButton').removeAttr('disabled').val('build');
});
}
Server Side Code:
Meteor.methods({jenkinsServiceBuild: function(userName) {
var url = "https://www.ynet.co.il";
//synchronous GET
var result = Meteor.http.get(url, {timeout:30000});
if(result.statusCode==200) {
var respJson = JSON.parse(result.content);
console.log("response received.");
return respJson;
} else {
console.log("Response issue: ", result.statusCode);
var errorJson = JSON.parse(result.content);
throw new Meteor.Error(result.statusCode, errorJson.error);
}
}
});
The site 'https://www.ynet.co.il' has an incorrectly installed SSL certficate for that domain. It's using akamai's certificate.
If you know and trust the site and its for nothing too secure just remove the s in https
var url = "http://www.ynet.co.il";
Also I'm not sure the code will work, looking at the site it serves html content but this line:
var respJson = JSON.parse(result.content);
Suggests it serves JSON content. If it does server json content use this instead:
var respJson = result.data;

Node.js net library: getting complete data from 'data' event

I've searched around, and either can't find the exact question I'm trying to answer, or I need someone to explain it to me like I'm 5.
Basically, I have a Node.js script using the Net library. I'm connecting to multiple hosts, and sending commands, and listening for return data.
var net = require('net');
var nodes = [
'HOST1,192.168.179.8',
'HOST2,192.168.179.9',
'HOST3,192.168.179.10',
'HOST4,192.168.179.11'
];
function connectToServer(tid, ip) {
var conn = net.createConnection(23, ip);
conn.on('connect', function() {
conn.write (login_string); // login string hidden in pretend variable
});
conn.on('data', function(data) {
var read = data.toString();
if (read.match(/Login Successful/)) {
console.log ("Connected to " + ip);
conn.write(command_string);
}
else if (read.match(/Command OK/)) { // command_string returned successful,
// read until /\r\nEND\r\n/
// First part of data comes in here
console.log("Got a response from " + ip + ':' + read);
}
else {
//rest of data comes in here
console.log("Atonomous message from " + ip + ':' + read);
}
});
conn.on('end', function() {
console.log("Lost conncection to " + ip + "!!");
});
conn.on('error', function(err) {
console.log("Connection error: " + err + " for ip " + ip);
});
}
nodes.forEach(function(node) {
var nodeinfo = node.split(",");
connectToServer(nodeinfo[0], nodeinfo[1]);
});
The data ends up being split into two chunks. Even if I store the data in a hash and append the first part to the remainder when I read the /\r\nEND\r\n/ delimiter, there's a chunk missing out of the middle. How do I properly buffer the data in order to make sure I get the complete message from the stream?
EDIT: Ok, this seems to be working better:
function connectToServer(tid, ip) {
var conn = net.createConnection(23, ip);
var completeData = '';
conn.on('connect', function() {
conn.write (login_string);
});
conn.on('data', function(data) {
var read = data.toString();
if (read.match(/Login Successful/)) {
console.log ("Connected to " + ip);
conn.write(command_string);
}
else {
completeData += read;
}
if (completeData.match(/Command OK/)) {
if (completeData.match(/\r\nEND\r\n/)) {
console.log("Response: " + completeData);
}
}
});
conn.on('end', function() {
console.log("Connection closed to " + ip );
});
conn.on('error', function(err) {
console.log("Connection error: " + err + " for ip " + ip);
});
}
My biggest problem was apparently a logic error. I was either waiting for the chunk that began the reply, or the chunk that ended it. I wasn't saving everything in-between.
I guess if I wanted to get all Node-ish about it, I should fire an event whenever a complete message came in (beginning with a blank line, ending with 'END' on a line by itself), and do the processing there.
You shouldn't do anything with the data you recieve, until you receive the end event. The end callback means that all data chunks have been sent through the stream to your callbacks. If data comes in more than one chunk, you need to create a variable within your function closure to store this data to. Most programs can work just fine ignoring this fact, because data usually comes across in one chunk. But sometimes it doesn't. It doesn't even necessarily depend on the amount of data. If you're in a situation where this is happening, I created an example that demos how to handle it. I basically used your code, but removed all the fluff... this is just demoing the logic you need to collect all the data and do work on it.
function connectToServer(tid, ip) {
var conn = net.createConnection(23, ip);
var completeData = '';
conn.on('connect', function() {
conn.write (login_string); // login string hidden in pretend variable
});
conn.on('data', function(data) {
completeData += data;
var dataArray = completeData.split('your delimiter');
if(dataArray.size > 1) { //If our data was split into several pieces, we have a complete chunk saved in the 0th position in the array
doWorkOnTheFirstHalfOfData(dataArray[0]);
completeData = dataArray[1];// The second portion of data may yet be incomplete, thise may need to be more complete logic if you can get more than one delimeter at a time...
}
});
conn.on('end', function() {
//do stuff with the "completeData" variable in here.
});
}
My problem was a logic problem. I was either looking for the chunk that began the message, or the chunk that ended the message, and ignoring everything in between. I guess expected the entirety of the reply to come in in one or two chunks.
Here's the working code, pasted from above. There's probably a more Node-ish way of doing it (I should really emit an event for each chunk of information), but I'll mark this as the answer unless someone posts a better version by this time tomorrow.
function connectToServer(tid, ip) {
var conn = net.createConnection(23, ip);
var completeData = '';
conn.on('connect', function() {
conn.write (login_string);
});
conn.on('data', function(data) {
var read = data.toString();
if (read.match(/Login Successful/)) {
console.log ("Connected to " + ip);
conn.write(command_string);
}
else {
completeData += read;
}
if (completeData.match(/Command OK/)) {
if (completeData.match(/\r\nEND\r\n/)) {
console.log("Response: " + completeData);
}
}
});
conn.on('end', function() {
console.log("Connection closed to " + ip );
});
conn.on('error', function(err) {
console.log("Connection error: " + err + " for ip " + ip);
});
}

Post reply with node.js doesn't work

I've been working on a node.js based server for a project. Currently, I have a script on an html page that POSTS data to a jsp page on the same server - which works. However, I can't seem to send data back down the pipe. I've noted the same with various node.js posting scripts.
EDIT: Where I say JSP, I just mean standard javascript; I just made pages with .jsp extensions instead of .js so I could still send scripts as .js.
EDIT 2: The headers /do/ get sent. It just appears that response.write() or reponse.end() aren't acutally sending anything.. I've tried gzipping the data and changing the transfer-encoding header to match with no luck.
Think I might wireshark it.
EDIT 3: Wireshark can't detect the POSTs for some reason >.>
EDIT 4: Noticed that response.write() is returning false. Not sure how to debug. I'll add some more code at the end.
Here's the JSP page's code.
/**
* This POST parser takes XML data and translates it as follows..
*
* XML -> JS Object -> XML
*
* This is so I can test some libraries.
*/
// Eyes, to inspect variables
var inspect = require('eyes').inspector({maxLength: false});
// This is an XML parser, that parses XML into standard JS arrays
var xml2js = require('xml2js');
// This one converts JSON (Or JS objects) to XML.
var jsontoxml = require('jsontoxml');
exports.seperateHeader = false; // We have no separate header function
exports.separateEnd = true;
exports.GET = function(query, request, response) { // Our GET function.
response.writeHead(200, { // Write the header
'Content-Type': 'text/plain; charset=utf-8'
});
response.end("No POST data here!"); // Tell the user that there was no POST data.
}
exports.POST = function(query, postdata, request, response) { // Out POST function.
var rootnode = undefined;
var realdata = undefined;
var result = undefined;
if( postdata["data"].startsWith("<?xml") ) // It's XML, parse it
{
console.log(" | Detected XML.");
var parser = new xml2js.Parser(); // Create an XML parser
parser.parseString(postdata["data"], function (err, data) { // Parse the XML from the POST data
if(err){
inspect(err); // If we have an error, inspect it with eyes
}
else
{
// inspect(result); // Removed; printed the XML data as an array
for (var prop in data) { // Get the root node of our XML; this is the command
rootnode = prop;
break;
}
realdata = data[rootnode]; // Get the data without the root node
result = data;
}
});
}
else // Try to parse it as JSON
{
console.log(" | Detected JSON.");
result = JSON.parse(postdata["data"]);
for (var prop in result) { // Get the root node of our JSON; this is the command
rootnode = prop;
break;
}
realdata = result[rootnode]; // Get the data without the root node
}
console.log(" | Before: ")
inspect(postdata["data"]); // Inspect the data we've got (XML or JSON)
console.log(" | Native object: ")
inspect(result); // Inspect the data that's been parsed to an object
console.log(" | XML: ")
xmldata = jsontoxml.obj_to_xml(result) // Object -> XML
xmldata = '<?xml version="1.0" encoding="UTF-8"?><Request>' + xmldata + "</Request>"; // WUPOS extra XML stuff and the XML header
inspect(xmldata); // Inspect the XML created from the object
response.writeHead(200, { // Write the header
'Content-Type': 'text/plain; charset=utf-8',
'Content-Length': xmldata.length
});
response.write(xmldata);
}
And here is the internal code for the http response..
var fs = require('fs');
var url = require('url');
var path = require('path');
var querystring = require("querystring")
var ext = require("./ext.js").ext // For getting MIME types (I know, there's another module for this)
// Logging function
function Log(message, prefix, isSecure)
{
if (!prefix)
{
prefix = " ";
}
else
{
if (isSecure)
{
prefix = "HTTPS";
}
else
{
prefix = "HTTP ";
}
}
console.log(prefix + " | " + message);
}
exports.Log = Log;
// httpRequest; this function serves standard HTTP requests
function httpRequest(request, response, isSecure) {
request.setEncoding('utf-8'); // Set the encoding
requrl = url.parse(request.url, true); // Parse the URL
reqhost = request.connection.address();// Get the IP and port of the user
if (requrl.pathname == "/") // If they were requesting the root..
{
if (path.existsSync("../html/index.jsp")) // If index.jsp exists..
{
reqfile = "/index.jsp"; // Remember that we want that file
}
else // Otherwise, index.html
{
reqfile = "/index.html";
}
// Log it
if (requrl.search) {
Log(
"[" + reqhost.address + ":" + reqhost.port + "] " + request.method + " " + reqfile + requrl.search + " (Redirected from \"/\")",
true, isSecure
);
}
else {
Log(
"[" + reqhost.address + ":" + reqhost.port + "] " + request.method + " " + reqfile + " (Redirected from \"/\")",
true, isSecure
);
}
}
else // If not,
{ // Log it,
Log(
"[" + reqhost.address + ":" + reqhost.port + "] " + request.method + " " + requrl.href
, true, isSecure
);
reqfile = requrl.pathname; // Remember which file was requested
}
if (reqfile.endsWith(".jsp")) { // If the file is a JS page
try { // Try..
reqjs = require("../html/" + reqfile); // ..to import the code from our script
if (reqjs.separateHeader) { // If the script has a separate function for sending the header..
reqjs.headers(request, response); // Send it
}
if (request.method == 'GET') // If we have a GET
{
reqjs.GET(requrl.query, request, response); // Run the script's GET function
}
else if (request.method == 'POST') // If we have a POST
{
// Grab all the POST data
var fullBody = '';
request.on('data', function(chunk) {
if(fullBody.length > 1e6) // If we're getting a massive amount of data, kill the connection
{
Log("POST flood attack / faulty client detected. Connection closed.", false, isSecure);
request.connection.destroy();
return;
}
fullBody += chunk.toString();
});
request.on('end', function() {
var postdata = querystring.parse(fullBody); // Parse the POST data
if (reqjs.POST) // If the script has a POST function,
{
reqjs.POST(requrl.query, postdata, request, response); // Call it
}
else
{ // Otherwise, just call the GET function
reqjs.GET(requrl.query, request, response);
}
});
}
}
catch(e) // If there's an error..
{
response.writeHead(500, {
'Content-Type': 'text/plain'
});
response.write("Error: " + e); // Send it to the browser
Log("Error: " + e, false, isSecure); // Log it
}
response.end(); // Finish the response
}
else // If the file is not a JS page,
{
fs.readFile("html" + reqfile, function(err, data) { // Read the file in
if(err) { // If there's an error..
errortype = err.message.split(",")[0]; // ..get the error's code
if (errortype == "ENOENT") // File not found
{
response.statusCode = 404;
response.end("File not found: " + reqfile); // Send them a 404
Log("File not found.", false, isSecure); // Log it
}
else if (errortype == "EISDIR") // File is actually a directory
{
if (path.existsSync("html" + reqfile + "/index.jsp")) // If there's an index.jsp file here..
{ // Redirect the browser
Log("Found index.jsp", false, isSecure);
response.writeHead(301, "Moved Permanently", {
"Location" : reqfile + "/index.jsp"
});
response.end("Please click here.")
return; // Return, so we don't have to wrap the next section of code in braces
}
else if (path.existsSync("html" + reqfile + "/index.html")) // Or, if there's an index.html file here..
{ // Redirect the browser
Log("Found index.html", false, isSecure);
response.writeHead(301, "Moved Permanently", {
"Location" : reqfile + "/index.html"
});
response.end("Please click here.")
return; // Return, so we don't have to wrap the next section of code in braces
}
// If we don't have those files, list them
Log("Listing files in html/"+reqfile, false, isSecure); // Log it
response.statusCode = 200; // Use Node.js's standard "OK" header
// Write out some HTML
response.write("<html><head></head><body>\n");
response.write("<h1>Directory listing: " + reqfile + "</h1>\n");
response.write("<ul>\n");
// List off the files
var filelist = fs.readdirSync("html" + reqfile);
// For every file..
for (element in filelist)
{
// Compile some HTML
var datastr = "";
datastr += "<li>";
datastr += "<a href=\"" + reqfile + "/" + filelist[element] + "\">";
if (filelist[element].endsWith(".jsp") || filelist[element].endsWith(".html"))
{ // If it ends in html or js, it's a normal page, so colour it green
datastr += "<span style=\"color: green;\">";
datastr += filelist[element];
datastr += "</span></a>";
}
else
{ // Otherwise, just put it in the list
datastr += filelist[element];
datastr += "</a>";
}
datastr += "</li>\n";
response.write(datastr); // Write out the HTML and go around again
}
response.end("</ul></body></html>"); // Finish the response
}
else
{ // There was some other problem when opening the file
Log("Could not open file: " + err, false, isSecure); // Log it
response.statusCode = 501 // Internal server error code
response.end("Could not open file: " + err.message); // Tell the browser
}
}
else
{ // No problems or anomalies. Serve it!
var contenttype = ext.getContentType(ext.getExt(reqfile).replace(".", "")); // Get the MIME type
Log("Content-Type: " + contenttype, false, isSecure); // Log it
response.writeHead(200, "OK", {
'Content-Type': contenttype
// 'Access-Control-Allow-Origin': 'http://b.localhost:25566',
// 'Access-Control-Allow-Methods': 'POST, GET',
// 'Access-Control-Allow-Headers': 'Content-Type'
});
response.write(data); // Send the data (TODO: Send in chunks?)
response.end() // End
}
});
}
}
exports.httpRequest = httpRequest;
And the code for the html page..
<html>
<head>
<title>JS test A</title>
<script src="js/jquery.js"></script>
</head>
<body style="margin-left: 30%; margin-right: 30%;">
<div id="tests" style="float:left; width=40%;">
Test A
</div>
<div id="output" style="float:right; width=60%;">
<form id="form">
<textarea id="output" name="output"></textarea>
</form>
</div>
<script>
$(document).ready(function(){
$("a#a").click(function(event){
text = $("textarea").val();
$("textarea").val(text + "POST test.\n");
text = $("textarea").val();
var http = new XMLHttpRequest();
jsonobj = {
array: {
obj1: "obj1",
obj2: "obj2"
},
obj3: "obj3"
}
var url = "postTest3.jsp";
var params = "data="+JSON.stringify(jsonobj);
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
$("textarea").val(text + http.responseText);
}
else
{
$("textarea").val(text + "Repsponded: " + http.status + "\n");
}
}
http.send(params);
});
});
</script>
</body>
</html>
EDIT 4: Additional code
{
// Grab all the POST data
var fullBody = '';
request.on('data', function(chunk) {
if(fullBody.length > 1e6) // If we're getting a massive amount of data, kill the connection
{
Log("POST flood attack / faulty client detected. Connection closed.", false, isSecure);
request.connection.destroy();
return;
}
fullBody += chunk.toString();
});
request.on('end', function() {
var postdata = querystring.parse(fullBody); // Parse the POST data
if (reqjs.POST) // If the script has a POST function,
{
postout = reqjs.POST(requrl.query, postdata, request, response); // Call it
if (postout) {
inspect(response.write(postout, 'utf8'));
}
}
else
{ // Otherwise, just call the GET function
reqjs.GET(requrl.query, request, response);
}
});
}
Does anyone have any ideas on this?
Okay, so, I fixed the problem. Thought I'd share my solution here.
Basically, after adding some inspect() calls, it turned out that because reponse.write() was being carried out asynchronously, and response.end() wasn't, response.end() was being called first. This is why response.write() returned false.
I fixed it by moving the response.end() into my asynchronous blocks.

Categories

Resources