API request from front-end using sails.io.js - websocket

I have a basic front-end (html, css, jquery) and I'd like to use sails.io.js to communicate with an API server (developped with sails, with cors enabled). The API is running on localhost:10000 but it will be on an another domain than the one of the webclient later on.
Directly from jquery, I can issue some get request to this API and get the expected results.
When it comes to websocket, I have some problems...
In the index.html (just to test), I put the following:
<script src="js/sails.io.js"></script>
<script type="text/javascript">
io.sails.url('http://localhost:10000');
io.socket.get('/data', function serverResponded (body, sailsResponseObject) {
// body === sailsResponseObject.body
console.log('Sails responded with: ', body);
console.log('with headers: ', sailsResponseObject.headers);
console.log('and with status code: ', sailsResponseObject.statusCode);
});
</script>
But Chrome's developer tools tell me
ReferenceError: io is not defined
Any idea ?
UPDATE
I'm serving index.html with a web server (python -m SimpleHTTPServer)
I've installed sails.io.js using bower.
I've try to make this test as simple as possible:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<script src="bower_components/sails.io.js/dist/sails.io.js"></script>
<script src="index.js"></script>
</body>
</html>
index.js:
window.onload=function(){
io.sails.url = 'http://localhost:10000';
io.socket.get('http://localhost:10000/data', function (body, response) {
console.log('Sails responded with: ', body);
});
};
My sails (0.9.16) API is only returning a json object on the GET /data route.
I have implemented a dummy __getcookie function in the api:
'get /__getcookie': function(req, res, next){
res.json({ok: 123});
}
And commented the line 481 in interpret.js (Scott comments below).
I have also modify config/socket.js with:
authorization: false,
=> I can now get the result from the /data route of my API :)
But... on each request I have the following error:
error: Error: No valid session available from this socket.

First of all, sails.io.js includes the code for socket.io.js, so there is no need to try and include that separately. You should remove this line:
<script src="bower_components/socket.io/lib/socket.js"></script>
Next, if you're just loading index.html from disk (rather than serving it from a web server), you'll need to tell the Sails socket client what URL to connect to:
io.sails.url = 'http://localhost:10000';
Put this anywhere before you start making socket calls; the library is smart enough to wait until its connected before trying to make the calls. So, altogether:
window.onload=function(){
io.sails.url = 'http://localhost:10000';
io.socket.get('http://localhost:10000/data', function (body, sailsResponseObject) {
console.log('Sails responded with: ', body);
console.log('with headers: ', sailsResponseObject.headers);
console.log('and with status code: ', sailsResponseObject.statusCode);
});
};
should work. You should be able to see in the console whether or not the socket connected by looking for the "io.socket connected successfully." message.

did you try with a / in front of the src, like:
< script src="js/sails.io.js">
Do you have the sails.io.js in the /assets/js/ folder (sails 0.10) or in the /assets/linker/js folder (sails 0.9 and below).
Did sails lift copied that js file to .tmp/public/js folder?
Where is your index.html file located?

Related

Golang Simulate Page Visit : Surf Not Triggering Javascript

I have a Go program that is just simulating a local web page being visited using Surf (gopkg.in/headzoo/surf.v1) but it seems that the Javascript on the page is not being executed. Just to test I have the web page doing an ajax call to another route on the server that will just output a response on the server side.
<html>
<head>
<script src="jquery.min.js"></script>
</head>
<body>
<script>
$.ajax ({
url : "/test",
type : "GET",
success : function(res) {},
error : function(res) {}
});
</script>
</body>
</html>
Then the Go Surf function to visit the page, this route also outputs a response on the server side which is showing up but the one from the ajax request is not showing up.
func simulateVisit() {
bow := surf.NewBrowser()
bow.SetUserAgent("LocalCrawler/1.0")
err := bow.Open("http://127.0.0.1/page")
if err != nil { fmt.Println(err) }
}
To make sure it is only happening from Surf I also tested it with Chromedp (github.com/chromedp/chromedp) which gave both responses correctly.
Is this a limitation with Surf or am I doing something silly?
Surf does not include a JS runtime. It does support the downloading of scripts, but it will never actually execute them.

Angular-ui-router templateUrl not working with Chrome and IE, but works for Firefox

Created a very simple Angular ui-router files to test, I found out "templateUrl" ('contact' state in my example code) in the stateProvider not working with Chrome and IE, but works for Firefox, however, 'template'('home' state in my example code) property works in Chrome/IE/Firefox.
My test project only contains two html files under same folder:
index.html
<html>
<head>
<script src="http://unpkg.com/angular#1.5/angular.js"></script>
<script src="http://unpkg.com/angular-ui-router#1.0.0-beta.3/release/angular-ui-router.js"></script>
</head>
<body ng-app="main-app">
<a ui-sref="home">Home</a>
<a ui-sref="contact">Contact</a>
</br>
<ui-view></ui-view>
</body>
<script>
var myApp = angular.module('main-app', ['ui.router']);
myApp.config(function($stateProvider) {
var homeState = {
name: 'home',
url: '/home',
template: 'hello world!'
}
var aboutState = {
name: 'contact',
url: '/contact',
templateUrl: 'contact.html'
}
$stateProvider.state(homeState);
$stateProvider.state(aboutState);
});
</script>
</html>
contact.html
Phone: 416-1113333
There is nothing wrong with your example, it seems you are trying to serve the app via file:// protocol but browsers like Chrome does not allow XHR calls when using the file:// protocol.
Here is the same example accessible via the HTTP server that works identically across browsers.
Another options would be:
embed templates in your index.html file using the <script> directive:
http://docs.angularjs.org/api/ng.directive:script so your templates
are downloaded with the main HTML file and it is no longer necessary
to load them via XHR
change browser settings to allow XHR calls over the file://
protocol. For example, for Chrome follow this answer for a more details

Fetch terminal command (Nodejs) and send to specific port via AJAX

I'm actually working on a little application. I have one server written in C which is listening on the port 5260. In the other side I have a NodeJS client which is listening on the port 7777. A HTML page can be reach via this port. In the HTML page I have a simple button.
When I click on this one a message is sent to my NodeJS server and is written on the terminal. Now I would like to fetch this command and send it to my C server which is still running and waiting for a request.
My client.js :
var http = require('http');
var ejs = require('ejs');
var express=require('express');
var app = express();
app.engine('html', ejs.renderFile);
app.set('/', __dirname);
app.get('/', function(request,response) {
response.render('index.ejs.html');
})
var options = {
host: '192.168.1.154',
path: '/',
port: '5260',
method: 'POST'
};
app.post('/play', function(req, res){
var res = http.request(options);
console.log("START_BG;BG1\n");
});
app.listen(7777);
And my HTML file :
<html>
<head>
<script type="text/javascript" src="client.js"></script>
<script type="text/javascript">
function sendMessage() {
var xhr = new XMLHttpRequest();
xhr.open('POST', '/play', true);
xhr.onload = function() {
console.log(xhr);
};
xhr.send();
}
</script>
</head>
<body>
<button onclick="sendMessage()">VIDEO</button>
</body>
</html>
Well. I see some strange things in your code
1 You're making the post request to 192.168.1.254:5620/play without sending any data on it
2 You're not waiting fro the request to end and blindly print on your console without checking the result. Don't know if its the desired behaviour, but it seems a bit strange
Without more knowledge about the scenario is difficult to suggest an idea.
What is the answer you expect from the remote server?
It's suposed to print something in the (remote) console ?
What it should return via HTTP ?
Anyway I suggest you correct your code as follows:
app.post('/play', function(req, res){
var res = http.request(options, function(response){
// do any checking about response status and/or body if any
console.log("START_BG;BG1\n");
});
});

Loading local content through XHR in a Chrome packaged app

I'm trying to load in a web app that I've built using Backbone and it pulls in JSON and HTML template files that are stored locally. I was wondering with Chrome packaged apps whether it's possible to load these files by using some sort of 'get'/ajax request?
Currently I'm getting this...
OPTIONS chrome-extension://fibpcbellfjkmapljkjdlpgencmekhco/templates/templates.html Cannot make any requests from null. jquery.min.js:2
XMLHttpRequest cannot load chrome-extension://fibpcbellfjkmapljkjdlpgencmekhco/templates/templates.html. Cannot make any requests from null.
I can't find any real information on how to do this so any help would be great thanks!
Yes, it's totally possible, and it's easy. Here's a working sample. Try starting with this, confirm that it works, and then add back in your own code. If you hit a roadblock and come up with a more specific question than whether XHRs work in packaged apps, you might want to ask a new question.
manifest.json:
{
"name": "SO 15977151 for EggCup",
"description": "Demonstrates local XHR",
"manifest_version" : 2,
"version" : "0.1",
"app" : {
"background" : {
"scripts" : ["background.js"]
}
},
"permissions" : []
}
background.js:
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create("window.html",
{ bounds: { width: 600, height: 400 }});
});
window.html:
<html>
<body>
<div>The content is "<span id="content"/>"</div>
<script src="main.js"></script>
</body>
</html>
main.js:
function requestListener() {
document.querySelector("#content").innerHTML = this.responseText;
};
onload = function() {
var request = new XMLHttpRequest();
request.onload = requestListener;
request.open("GET", "content.txt", true);
request.send();
};
content.txt:
Hello, world!
You are making a request from a sandboxed page, and sandboxed pages have a null origin.
I have posted this issue question on the Google Group.
Unless Chrome decides to changed the sandbox policy, it appears the only workaround is to make XHR requests from a non-sandboxed page and use Chrome's message passing API to give it to your sandboxed page.
I don't know why it has to be so difficult.
EDIT:
The answer from the Chrome Team was to change the CORS header to *.
I believe your problem is on the server side, rather than the client side. The server needs to send the following header for jQuery to deal with the response:
Access-Control-Allow-Origin: *
The problem, with this, however, is that any page can load that content now. Once you know the ID of your extension, you can change that header to something like:
Access-Control-Allow-Origin: chrome-extension://gmelhokjkebpmoejhcelmnopijabmobf/
A short test of something like the following showed these to work:
<h1>Content Below</h1>
<div id="loadme"></div>
<script src="jquery-1.9.1.min.js"></script>
<script src="app.js"></script>
// app.js
$(document).ready(function() {
$.get('http://localhost:8080/content.php', function(data) {
$('#loadme').html(data);
});
});
This would fail with the following message if I didn't add the Access-Control-Allow-Origin header:
XMLHttpRequest cannot load http://localhost:8080/newhope/deleteme.php.
Origin chrome-extension://gmelhokjkebpmoejhcelgkfeijabmobf is not allowed by
Access-Control-Allow-Origin.
Once I added the Access-Control-Allow-Origin header on the php response, it worked fine.
Again, setting this to * may be a security risk as any browser page anywhere is allowed to load it inline.

SignalR not sending web requests on start

So, We are implementing some messaging system with signalR.
We included signalR through the latest version of Nuget.
The application is hosted on IIS 7. We have disabled all the URL Rewrite rules.
We are using a hub, see the following code:
[HubName("messages")]
public class Messages : Hub
{
public void Send(string message)
{
Clients.showPopUp(message);
}
}
The include files in the view:
<script src="#Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.signalR.js")" type="text/javascript"></script>
<script src="#Url.Content("~/signalr/hubs")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/Messages/Messages.js")" type="text/javascript"></script>
Content of Messages.js:
$(function () {
var messages = $.connection.messages;
messages.showPopUp = function (message) {
console.log("test");
};
$.connection.hub.start(function () {
console.log('connected');
});
});
Called when a message is submitted:
$.connection.messages.send($('#Body').val());
So what we get: no errors in Google Chrome console, no xhr request what so over for signal.
We have checked if the /signalr/hubs exists and it does, also /signalr/negotiate returns the following json:
{"Url":"/agenda/signalr","ConnectionId":"a4215b26-32f1-4a52-bf6d-4de096298a07","TryWebSockets":false,"WebSocketServerUrl":null,"ProtocolVersion":"1.0"}
When we call send we get the following in the console:
Uncaught SignalR: Connection must be started before data can be sent. Call .start() before .send()
If we debug signalR, we see start was called, but we don't hit the error or success of the jQuery ajax call and there are no xhtml requests what so ever. What are we doing wrong?
Try checking out this issue: https://github.com/SignalR/SignalR/issues/328
Solution
In jquery.signalR.js change all the
$.ajax(url, {options});
to
$.ajax({ url: url, other options...});

Resources