Call express (node.js) APIs from static HTML page on host - ajax

I have a static HTML page, hello.html. If I double click hello.html, it opens up in my default browser, and displays the HTML properly, but in the browser's search bar, instead of having a URL with a hostname, what displays is the local filepath for hello.html on my computer.
I have made a simple express web server on my computer, using express (node.js). It is set to listen on port 8080, and has a simple GET api. (The API right now does something simple like call 'ls'). I wanted to be able to call that GET API, from my static hello.html. In my static HTML page, I use jquery to make an ajax call to this api, calling it as http://127.0.0.1:8080/myapi. Once I start the express server and load the page, looking at the console logs, the requests to myapi are going through when I load the static HTML page in the browser (the ls response is getting logged on the console), however, the jquery ajax in the HTML page, always executes the error function, even when I'm setting the response as 200.
I was reading a lot about why this happens, and read it could be due to CORS issue. However, there is no hostname I can specify on the server side, to allow in this case, since there is not actually a web server running, and so there is no actual host name associated with my static HTML page.
Is this even possible to do? (To have a static HTML page on your computer with no web server running, make your own express server with APIs, and call those APIs from the static web page?)
Example:
hello.html
<html>
<head>
<title>Hello World</title>
</head>
<body>
<script src"js/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type: "GET",
url: "http://127.0.0.1:8080/myapi",
contentType: 'application/json',
success: function(response) {
alert("success!");
},
error: function(jqXHR, textStatus, errorThrown) {
alert("error");
},
});
});
</script>
<p>Hello World!</p>
</body>
</html>
myserver.js:
var express = require('express');
var shelljs = require('shelljs');
var app = express();
app.get('/myapi', function (req, res) {
shellStr = shelljs.exec('ls');
if ( shellStr ) {
console.log("successful call on server side");
res.status(200);
res.json({ ls: shellStr });
}
else {
console.log("failure status on server side");
res.status(500).json({ error: "Could not do ls"});
}
})
var server = app.listen(8080, function() {
console.log("Listening on 8080");
})
I am starting up the server by giving 'node myserver.js', and then I open the static HTML page in the browser. When it loads, the API call is being made, as I see the server side console output, and it's going as success. However, back in the static html, the ajax call's 'error' function is always executed.

I got it to work!
In case anyone else ever wonders, and is new to express and web servers like myself.
The key was to have express serve hello.html as well. It is simple to do this.
I had my express server in a directory like this:
myserver/myserver.js <-- this is my express server
I moved all of my static html files, in to a directory at the same level.
myserver/htmlfiles/ <-- this directory has 'hello.html'.
Now, in myserver.js, I added the following line near the top, just after var app = express():
app.use(express.static('myhtml'))
What this does, is it will tell express to serve any static files in the directory myhtml (will search for that directory, relative to where the myserver.js is.)
If I restart the express server (kill the current one then just run 'node myserver.js' again), and go to the browser, if I visit http://127.0.0.1:8080/hello.html - the page shows up!
Now the domain origin is the same, and when the ajax call is made to the api, it is successful in the browser, too!
(Note - I did have an issue at first after these changes, because my ajax URL in hello.html was calling http://localhost:8080/myapi, but I was displaying hello.html in the browser via http://127.0.0.1:8080/hello.html. Once I changed the ajax URL being called to http://127.0.0.1:8080/myapi - everything worked. Similarly, if I open the browser and go to http://localhost:8080/hello.html and display hello.html that way, if the ajax URL being called is http://127.0.0.1:8080/myapi - the ajax call will go in to the 'error' function. It seems that the hostname you are using in the ajax URL in the HTML page, must be the same (127.0.0.01 vs. localhost) as the hostname you are using to visit the html page in the browser when the call is made.)

Related

AJAX call won't display

There is a chunk of my website that won't display on the new web server. This page is currently being hosted on Windows 2003, IIS 6 and I'm moving it to Windows 2008, IIS 7. There is a div being populated by an ajax call to another page in the site which is not displaying on the new server's localhost. However, my test machine is running the exact same code from IIS Express (Windows 7) and it works correctly.
I believe the issue has to do with IIS. Is there a setting that would prevent AJAX from executing? I've narrowed the problem down to the following code block.
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
ajax: false,
url: 'Newsfeedbrief',
success: function(response) {
$(".newsFeedContainer").html(response)
console.debug(response)
}
});
});
</script>
In a browser where the newsFeedContainer is populated the console prints the html, but not in the browser where the text is missing.
It started working after adding the extension to the page.
url: 'Newsfeedbrief.aspx'

Vue.js + Vue Resource No 'Access-Control-Allow-Origin'

Cross site ajax request with Vue.js 1.0 and Vue Resource. I get the following error: XMLHttpRequest cannot load http://dev.markitondemand.com/MODApis/Api/v2/Lookup/jsonp?input=NFLX&callback=handleResponse. No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have a basic understanding of the problem but not sure how to add a callback function with the request or if that is the best solution for this example. I put in the full request URL here just to make it easier to follow.
new Vue({
el: '#stockList',
data: function() {
return {
query: '',
stocks: []
};
},
ready: function() {
this.getStocks();
},
methods: {
getStocks: function() {
this.$http.get('http://dev.markitondemand.com/MODApis/Api/v2/Lookup/jsonp?input=NFLX&callback=handleResponse',
function(data) {
this.stocks = data;
}
);
}
}
})
I have almost zero understanding of networking, but I was able to get several remote apis to work using:
this.$http.jsonp
instead of
this.$http.get
"No Access-Control-Allow-Origin" header usually is a problem with the server. It means that the server is configured to only allow a person access to the API if the request comes from the same domain as the server. You either need to run the script from the website that you are requesting data from, or you need to change the server config to allow access to all domains.
If you don't have access to the server, and you don't want to run the script in the browser, then I think what you could do is use a headless browser like PhantomJS to navigate to the page, insert a script element into the dom that contains you script, execute the function and then return the data from the API. I could write the code out for you, but to be honest, it's a bit complex. You would have to know how to use node.js, and phantom.js. I've personally only used phantom.js for the Node 'html-pdf' package, but I'm sure with a little bit of reading you could figure out how to do it.
Set your local environment to http instead of https if you have no control over dev.markitondemand.com.

ajax from same site as JS reference file?

I have a JS file running on my site, it works fine.
Now I want to put on another site with the full url of the script back to my site.
<script src="http://www-js.mydomains.com/some/path/file.js"></script>
now is it really still cross domain to an xml request on my server?
so in the file.js I have something like
dojo.xhrGet({url: '/some/path/file.xml', sync: true, handleAs: 'xml', error: function(result,args){alert(result.responseText+'-'+args.responseText)}, load: function(result){ ....
this just dies on other sites (great dojo response of undefined)... is there away around it
I think you should use "script" dojo/request/script instead of xhr.
require(["dojo/request/script", "dojo/dom", "dojo/dom-construct", "dojo/json", "dojo/on", "dojo/domReady!"],
function(script, dom, domConst, JSON, on){
on(dom.byId("startButton"), "click", function(){
domConst.place("<p>Requesting...</p>", "output");
script.get("helloworld.jsonp.js", {
jsonp: "callback"
}).then(function(data){
domConst.place("<p>response data: <code>" + JSON.stringify(data) + "</code></p>", "output");
});
});
});
http://dojotoolkit.org/reference-guide/1.9/dojo/request/script.html
now is it really still cross domain to an xml request on my server?
Yes. The origin is based on the URI of the HTML document hosting the script, not the URI the script was sourced from.
You should send the HTTP headers defined in the CORS specification to allow other sites to use your script (or their own scripts) to access content on your server.
Additionally, URIs accessed by JS are also relative to the document and not the script, so you will need to use an absolute or scheme relative URI instead of the server root relative URI you are presently using.

sending an HTTP request with an unordinary method

I am trying to create a link on my web page that when accessed will cause an HTTP request with an unordinary method to be sent (for the sake of the example, the method is POSTS).
I know that regular HTML forms support only GET and POST and AJAX should support PUT and delete. Is there a way to issue requests with a method different than these standard HTTP methods?
Thanks in advance.
==============
After the tips I adjusted my page to have the following HTML:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function(){
$("button").click(function(){
$.ajax({url:"http://www.example.php",type:"POSTS",dataType:"html"});
});
});
</script>
</head>
<body>
<button>Send Request</button>
</body>
</html>
Surprisingly, this did not work in Chrome and Firefox but did work in an updated version of IE:
When I tried to issue the request using Firefox and Chrome, the browser issued a request with an OPTIONS method and the following header:
Access-Control-Request-Method: POSTS
Only IE issued the request as per the requirement - using the POSTS HTTP method.
===
Turns out that the aforementioned HTML doesn't work.(The desired request with the custom header is not issued).
As I mentioned above, firefox and chrome issue an initial request with an Access-Control-Request-Method header , while IE doesn't issue a request at all.
I adjusted the browser security settings (enabled "Access data sources across domains),
but still, the browser did not issue the request.
I'm guessing there needs to be some further adjustments in the browser setting, does anyone have an idea how this can be solved?
Quick answer yes if you use javascript.
Methods are defined by the standard along with status codes however they are open to extension. Such as webdav which increases the method vocabulary.
Not all browsers support arbitrary http methods especially older versions of IE (surprise surprise!)
So you could simply have a link / button which calls a javascript function which makes your http request.
Simply using jQuery:
var request = $.ajax({
url: "script.php",
type: "POSTS",
data: { id : menuId },
dataType: "html"
});
request.done(function( msg ) {
$( "#log" ).html( msg );
});
request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});

Cross Domain issue(Working in IE not in other browser)

I am fetching data from a URL using an AJAX call. It is giving a json object to me.
When I run the application, the page is working fine in IE with a conformation that
the page is accessing information that is not under its control.
This poses a security risk. Do you want to continue?
But that is not working in other browsers like Firefox, Chrome, Safari, etc.
i don't know what is the problem. Please explain to me why it is occurring and how to solve the issue?
My Code:
<!DOCTYPE html>
<html>
<head>
<title>Search Engine</title>
<script src="JS/jquery-1.4.2.min.js"></script>
<script>
$(document).ready(function () {
$.support.cors = true;
// create a script tag element
var script = document.createElement("script");
// set the attribute, using the URL to pass data via query parameters
script.setAttribute("src", "http://192.168.13.111:7090/?uname=bhagirathip&wt=json&fl=*,score");
script.setAttribute("type", "text/javascript");
// add the script tag to the document head, forcing an HTTP request
document.getElementsByTagName("head")[0].appendChild(script);
});
function Search() {
function callbackJsonHandler(data) {
alert(data); // This is the JSON data
}
}
</script>
</head>
<body>
<form id="form">
<div style="text-align: center">
<input type="search" id="searchInput" autofocus />
<input type="button" id="btnSearch" onclick="Search()" value="Search" />
</div>
</form>
</body>
</html>
You can't make cross-domain AJAX calls across domains. This is a security feature in web browsers to prevent malicious JavaScript code from scraping rendered data in a web page and then shipping it off to some rogue website on some other domain.
By restricting AJAX requests to same domain, browser vendors ensure that JavaScript imported from other sources cannot send data to any server other than the server the HTML page was served from.
In Internet Explorer, it's prompting you, but any smart user who encounters such a message is likely to say no. Presenting your users with such warning messages is not a good design practice and does not inspire confidence in the legitimacy of your application.
The only way that you can send data across domains is to use a browser hack technique called "script tag remoting", which essentially involves using HTML elements that aren't restricted by the same domain policy. For instance script tags can make HTTP GET requests to any server:
// create a script tag element
var script = document.createElement("script");
// set the attribute, using the URL to pass data via query parameters
script.setAttribute("src","http://192.168.9.11/userInput/?key="+userInput);
script.setAttribute("type","text/javascript");
// add the script tag to the document head, forcing an HTTP request
document.getElementsByTagName("head")[0].appendChild(script);
Using this method, you can send data to a remote server. Note that, to get JSON data back, you must wrap it, or pad it, in a JavaScript function and define a callback in the JavaScript code to handle the response:
function callbackJsonHandler(data) {
alert(data); // This is the JSON data
}
And your server-side code must return content text/javascript, calling the handler, and passing your JSON as an argument:
callbackJsonHandler({"key":"value","key1":"value2"});
When the browser downloads the JavaScript to the browser, the JavaScript runs immediately, giving you a hook to use to access the JSON in the response.
Since you're using jQuery, you can also check out jQuery JSONP, or JSON with Padding, which can be used to generate a JavaScript response so that you can handle callbacks from these requests to the remote server. Note that the server must be setup to handle JSONP requests for this to work properly, similar to the above setup.
Another solution to the issue of making cross-domain requests from a browser whose HTML document is served from exampleA.com to a server whose domain is exampleB.com is to use a proxy.
Let's assume that the HTML document you're working with is served from exampleA.com. You own exampleA.com, and you can access the server side and client side code. exampleB.com, on the other hand, is a remote server owned or controlled by someone else. exampleB.com has some data you want to use in exampleA.com.
We know that AJAX won't work, because of the same origin policy, which is in place to protect rogue apps from doing bad things with people's data. However, servers aren't restricted to same domain policy. This means that your app can do the following:
||exampleA.com/test.html|| ---> http req --> ||exampleA.com/getData|| --http req --> ||exampleB.com/getJSON||
Server-side: (As in your server, exampleA.com):
In other words, on your server that you're using to serve the HTML, you write some code that makes an HTTP request from your server to the third-party server:
// JSON URL which should be requested
$json_url = 'http://www.exampleB.com/getJSON';
// Initializing curl
$ch = curl_init( $json_url );
// Configuring curl options
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json')
);
// Setting curl options
curl_setopt_array( $ch, $options );
// Getting results
$result = curl_exec($ch); // Getting JSON result string
See Getting JSON Data with PHP Curl for more details. Each server-side platform has the ability to make HTTP connections to servers.
// now, send the data in the response
HttpResponse::status(200);
HttpResponse::setContentType('application/json');
HttpResponse::setData($result);
HttpResponse::send();
See PHP HTTPResponse. Again, whatever language you're working with should have the ability to return data from a string.
Put the above code in a file called "getJSON.php", assuming you're using PHP. Make sure there is no whitespace between the opening <?php and the beginning of the document; otherwise, you will not be able to set the headers. There is likely a better way to send this response, but since your platform isn't specified, I'll leave that as an exercise for the reader.
Client-side code:
var searchURL = "/getJSON.php"; //From this URL json formatted data is present.
$.ajax({
url: searchURL,
type: 'GET',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
try {
alert(data);
}
catch (err) {
alert(err);
}
}
});
Now, in the above JavaScript code, you make a same-domain AJAX request to your server exampleA.com, and then your server makes a request on your behalf to exampleB.com to get the data, then exampleA.com returns the data in the response to the browser.

Resources