Ajax request returning entire script - javascript

I have been looking for a solution for this days ago... so basically I have 2 files: index.html and hellonode.js. Index.html has a div with text and a button that is supposed to make a request to hellonode.js when clicked. hellonode.js is supposed to receive requests and send a response to them.
hellonode.js:
var http= require('http');
function onRequest(request, response){
console.log("request has been received");
response.writeHead(200, {"Context-Type": "text/plain"});
response.write("<h1>response here!</h1>");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("server is running");
here is my index.html:
<!DOCTYPE html>
<html>
<head>
<script>
function loadXMLDoc() {
var xmlhttp;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById('myDiv').innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET", "hellonode.js", true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="myDiv">
<h2>content</h2>
</div>
<button type="button" onclick="loadXMLDoc()">Your response content should appear here</button>
</body>
</html>
Im using node js and a apache server (the binary version on Apachelounge.com), and put inside the htdocs folder those 2 files and then start my server, so when I access 192.168.0.102 from my other computers, I get the index.html screen. Everything is fine until here. When I click the button and send the request, the response that I receive is the entire javascript code of hellonode.js. Why is that happening? I have a feeling that my hellonode.js isnt even receiving my request, and that the index.html is just reading the hellonode's content and showing it istead of actually sending a request to it. Im new to this server-side stuff. Thanks.

Apache HTTPD is an HTTP server. The JavaScript you have written is also an HTTP server.
You are making the request to Apache HTTP for the file containing JavaScript program.
You should be running the JavaScript program via Node.js (e.g. from the command line of the server) and then using XMLHttpRequest to make the request to http://example.com:8888/
Note, you will then run into this error, so you will need to modify the JavaScript program to include CORS headers in the response. (Or you could use Apache's mod_proxy to let you make the request to Apache and then forward it to the JavaScript server).

This is happening because you are requesting the file hellonode.js using a GET request.
You need to set up and end point which you can send the request to. For example.
You need to setup a node server not an apache one.

You're correct. By sending an XHR request to hellonode.js, it's just sending a request to retrieve the file, and then returning all of the contents of said file.
It looks like what you're trying to do is run a Node server. You're going to need to configure your server to be able to serve the Node app, instead of running it through Apache (unless you want to serve a Node app with Apache).
To do it locally, you should run node hellonode.js, and it will spin up a server using Node, and be able to serve resources like you're expecting.
(Still, in that case, though, sending an XHR request to a file is just going to return the whole file without running it)

Nodejs is not intended to be run with apache. Apache shows your html page properly because it is meant to serve html pages -apart from PHP scripts-, however, is not intended to serve node scripts. So the request is returning your node scripts just as a plain text, like when you request a .css or .js file asset from a web page in the browser.
You must set up a node script explicitly invoking it with the node command:
node hellonode.js
Or in linux:
nodejs hellonode.js
Then, if your request and your server side script are properly coded, nodejs will actually listen to the request and send the proper response.
However, keep in mind that serving pages with node is not as straightforward than with apache, and educate yourself in services like nodemon or pm2 will sure pay you off.

As an example xmlhttp.open("GET", "hellonode.js", true); can be xmlhttp.open("GET", "http://www.thomas-bayer.com/sqlrest/", true);

Once you type in your terminal:
node hellonode.js
the Nodejs server is running on your current directory and hellonode.js file is used to display the result when you browser to : localhost:8888 in other words your hellonode.js file is playing the role of index.php in the classical php application.
To achieve what you want you can use the built-in http module, or use a framework like Expressjs or others.

Related

Nodejs HTTP Createserver - unpredictable javascript execution while serving from html files

When I serve an html file, having some javascript, from my nodejs web server I get different results, compared to when I include the same javascript from an external source. I have verified that directly opening the html file with the javascript inline or external source works the same, as expected.
In the example below I get "Modified header" in h1 tag, whereas with javascript as external source I get "Unmodofied header" in h1 tag.
Can somebody explain how to rectify the problem? Thanks.
Code for nodejs web server:
var http = require('http')
var fs = require('fs')
http.createServer(function (request, response) {
fs.readFile('htmlfile.html', function(err, data) {
response.writeHead(200, {'Content-Type': 'text'})
response.write(data)
response.end()
})
}).listen(8081)
htmlfile.html is as follows:
<html>
<body>
<h1 id = "header"> Unmodified header</h1>
<!-- <script src="populate_header.js"></script> -->
<script>
function populate_header () {
document.getElementById("header").innerHTML = "Modified header"
}
populate_header ()
</script>
</body>
</html>
In a nutshell, your http server is not configured to send populate_header.js to the browser when the browser asks for it.
When you do this in your HTML file:
<script src="populate_header.js"></script>
You're telling the browser to send your web server a request for a resource named populate_header.js. But your web server does not have a request handler that looks at what file is being requested and serve that specific resource. Your web server always sends htmlfile.html no matter what resource is being requested. So, the browser asks for a script file and gets an HTML file (causing it to basically just ignore it). Thus, your Javascript in populate_header.js is never delivered to the browser and thus the script in it never runs.
When you include the script inline, the Javascript is delivered with the HTML and works just fine without requiring another route on your web server.
A node.js web server serves NO files at all by default. It only serves files that you create a route handler for. It is possible to create a single route that will serve lots of static files (when using the Express framework, express.static() does exactly that). But, by default, it does not serve any files.
As soon as you need more than one route handler, I would recommend using a very simple framework like ExpressJS because it will save you a lot of time and is very lightweight. But, if you were going to add a new route handler to your existing little web server, you could do so like this:
var http = require('http')
var fs = require('fs')
http.createServer(function (request, response) {
if (request.method === "GET") {
let fname;
// Look at what resource was requested and match that up
// with the appropriate file name
// DO not accept any resource requested because that could open up
// your server for people to request your actual server code files
switch(request.url) {
case "/":
fname = "htmlfile.html";
break;
case "/populate_header.js":
fname = "populate_header.js";
break;
default:
break;
}
if (fname) {
fs.readFile(fname, function(err, data) {
if (err) {
response.writeHead(404);
response.end();
} else {
response.writeHead(200, {'Content-Type': 'text'})
response.write(data)
response.end();
}
});
} else {
response.writeHead(404);
response.end();
}
}
}).listen(8081)
Here, you can see you're looking at request.url to see what exactly was requested and then sending that resource. It's also looking a request.method to only respond to GET requests. And, it's sending 404 responses when some other file is sent.
This would all be a lot simpler using the ExpressJS framework.
const express = require('express');
const app = express();
// look for matching static resources in the static_files subdirectory
app.use(express.static("static_files"));
// send the htmlfile.html file when / is requested
app.get("/", function(req, res) {
res.sendFile("static_files/htmlfile.html");
});
app.listen(8081);
Then, just locate all your static resources in a sub-directory below your main server directory named static_files and the Express framework will automatically look in that sub-directory for files that match the requested URL. This code adds one custom route for / that specifically sends the htmlfile.html file, and you can certainly customize that however you want.
For further discussion of how node.js servers don't send any files by default, see these other related answers:
Can't load local files when using NodeJS server
Resources not loading in express
ajax request gives a 404 with express server (chrome) loads successfully with firefox without a server?
How to get files above the server directory in Node.js

NodeJS: Send HTTPS request but get HTTP

I am building a website using NodeJS, and I deploy it to Heroku. But when I open the website, something went wrong. Here is the problem:
Code:
In the main source file of my web:
app.get('/', (req, res) => {
var data = {
rootURL: `${req.protocol}://${req.get('Host')}`,
};
res.render('home.html', data);
});
Then, in home.html, I include the following script:
<script type="text/javascript">
$.getJSON('{{rootURL}}'+'/about', {}, function(data){
// Code here is deleted for now.
}).fail(function(evt) {
// Code here is deleted for now.
});
</script>
Here I use hbs template, so {{rootURL}} is equal to the 'rootURL' property within the 'data' object rendered along with the 'home.html' page.
The '/about' is one of the APIs I designed for my web. It basically sends back something about the website itself and this information is wrapped in JSON.
Then, here comes the problem. The code works fine locally, and works well when I send HTTP request instead of HTTPS to Heroku. But if I send HTTPS request to Heroku, I'll get 'Mixed Content' Errors:
Errors I get in Chrome Console.
I then switched to 'Elements' tab in the developers tool, and I saw this:
The schema is HTTP, not HTTPS!
I'm very confused here. I just grab the 'protocol' property within the 'req' object, and fill in the template with it. So, I'm assuming if I enter '[my-website-name].herokuapp.com' with 'https' schema in my Chrome Browser, my nodeJS app deployed on Heroku should get 'https' for req.protocol. But Apparently it's not the case. What is wrong here?
I assume you don't actually have an SSL certificate? Heroku will be providing the HTTPS, but it will then translate it to normal HTTP internally when it hits your express endpoint, which is why it sees req.protocol as HTTP.
Is there any point in even providing the URL to getJSON? Why not just send it $.getJSON('/about', callback) and let the browser handle that?
Also, you haven't hidden your URL in that first image you uploaded, if that's what you were intending.
Heroku router is doing SSL termination, so no matter if you connect via http or https, you get http on your side. Original protocol is however set in X-Forward-Proto header. You need use this value.

How does Electron proxy URLs?

I created a small server which, for now, just outputs the request.url:
const http = require('http');
http.createServer(onRequest).listen(8080);
function onRequest(clientRequest, clientResponse) {
console.log(clientRequest.url);
}
Using the Electron APIs we can set up a proxy: to proxy all the urls through this server.
So, I'm running my server on localhost:8080 and use the --proxy-server http://localhost:8080 to redirect the traffic through my proxy server. This allows me to change some snippets in the HTML and only then render it in Electron.
When I access http://ionicabizau.net the request.url on the server side is http://ionicabizau.net.
How come that we can override the request url in such a way? What does Electron in the background?
First I thought that it just has to do with appending it like this:
http://localhost:8080/http://ionicabizau.net
But actually, that arrives on the server like /http://ionicabizau.net (notice the first slash).
What's the magic that Electron does to change the url of the request object?
When Electron (or anything else) makes an HTTP request, it connects to the target server and port and sends a message like the following:
GET / HTTP/1.1
Host: www.example.com
Most servers interpret this as an HTTP request for the full URL http://www.example.com/. When you specify a proxy server, that affects what server the HTTP client connects to, but it doesn't change the content of the request (so the requested URL is still http://www.example.com/).
So there's really nothing special that Electron needs to do to "override" the request URL... any HTTP client specifies the request URL as part of the message it sends to the server, and this is independent of which server that message is sent to.

No need to set up a local server with Node.js?

I see when I want write a Node.js web application on my local machine, I don't need to set-up a local server using WAMP or MAMP. What is node.js really doing behind the scenes? I am providing this code to make a simple hello world web app:
var http = require("http");
http.createServer(function(request,response){
response.writeHead(200, {"content-type":"text/html"});
response.write("hello world");
response.end();
}).listen(8080);
console.log("server is running....");
When loading in my browser URL bar "localhost:8080" it works.
How this is working as and why don't I need a local server when working with Node.js?
You do have a local server... it's your Node.js application.
When you call http.createServer(), it creates an HTTP server. When you call .listen() on that server, it binds to the requested port, and optionally requested address, and listens for connections. When data comes in on those connections, it responds like any other HTTP server.
The HTTP server uses your request/response callback, firing it whenever a valid HTTP request comes in.
Because node comes out of the box with all the libraries you need to run a webserver, the http library that you are using is opening the 8080 port and handling the request with the function you provided
This part:
function(request,response){
response.writeHead(200, {"content-type":"text/html"});
response.write("hello world");
response.end();
}
No, you don't need it. Because node itself can be your webserver, just like in your example. Node is built on V8, which is chrome JavaScript engine .
Take a look a Express js module that gives you lots of features out of the box

Javascript Server Side Events with C-client Server Program

Im looking for feasibility of calling C object(for copying a file from client to server) via Javascript Eventsource.
Ex:
I have a C-Client Program which can be executed as below:
./client ip
executing above file will
send a file from client machine to server running at port 8888.
Server will be running at 8888 will receive the file and will write at /folder1/receivedfile.
./server ip
I need to do this in Javascript Event source.
Javascript code example:
if(window.EventSource){
var source =new EventSource("c-object");
}else{
// Result to xhr polling :( xhttprequest
}
It is feasible. Your second line would be something like this:
var source = new EventSource("http://myserver.example.com:8888/c-object");
Your server must be running HTTP protocol, of course. If going down this route, be aware that calling a resource on a different origin will need all the CORS workarounds. In this case the resource is c-object, and the different origin is because of using a different port to where the HTML was served from.
Alternatively you could use Apache, and start c-object as a cgi program. Then it just needs to interact on stdin/stdout.
But, taking a step back, are you sure it is EventSource you want? If you are just trying to send a signal to the server to tell it to copy a file, and not receiving any data, then use a normal AJAX request. SSE is for the server to stream data to the client, one-way, continuously. After the initial connection is made, SSE cannot send anything to the server.

Categories

Resources