I want to have a route on my sailsjs node server that is a socket connection. I want to then send a rest request to that route from outside the app and have the socket hear the event and update the UI of my app.
So far all I have seen on the web is to have a websocket server by itself. Is there no way to integrate it into an existing server?
I'm a bit lost here. Can anyone point me to a tutorial that is doing this?
Question: How do I send a rest request to my server from outside the app and have the server update the UI of my app?
If you need more clarity here, please let me know.
You Have to use WebSockets I think. The UI does not know anything about the server unless it is notified. The only other way to have it running without WebSockets is to have a long polling AJAX request, but that solution would work for a limited use cases.
Adding a Socket.io server to a node server is pretty trivial, I would give it a try.
Use socket.io, it can be added to every Node.js server. For example:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs');
app.listen( 80 );
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data);
});
}
io.set('log level', 1);
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
You can use any socket event here.
Related
I'm using Axios and React in my frontend app. When I'm trying to send POST request over HTTPS with Axios (xhr, fetch) and faced with the strange issue - my POST request turns into GET in Edge dev tools.
Here is my request:
const response = await axios.post(
config.local + "/api/login/credentials",
{
login,
password
}
);
Then I tried to dig dipper - created a simple HTTPS server and tried to send POST request from the client.
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
};
const PORT = 8188;
function handleRequest(req, res){
console.log(req.method);
}
const server = https.createServer(options, handleRequest);
server.listen(PORT, function(){
console.log("Server listening on: https://localhost:" + PORT);
});
And then, as I understand it, that request does not reach the server.
Here are some links:
Issue link 1
Issue link 2
Is there any error in console? You could use Fiddler to trace the network traffic and see the details. Also mentioned in the first link you provided, you could also try the two solutions in your GitHub link:
Solution 1:
My issue is caused by HTTPS; the backend is requiring HTTPS while I send an HTTP post from front side. Now I fixed by changing both to HTTPS.
Or Solution 2:
I solved it by passing the data in a different format using the "URLSearchParams " class.
I had the same problem with:
Microsoft Edge 44.18362.267.0
Microsoft EdgeHTML 18.18362
Windows 10
I think the problem is that Edge only supports certain data types in post requests. If you want to use the content-type 'application/x-www-form-urlencoded' then use URLSearchParams to make it work in Edge and other browsers like Firefox and Chrome. Passing a querystring seems not to work in Edge even if it does in other browsers.
Modifying the original post source code, the result would be:
import Axios from 'axios'
import Promise from 'es6-promise'
Promise.polyfill()
const URL= 'http://192.168.0.112/account/login/username'
// Use URLSearchParams instead:
const dataParams = new URLSearchParams()
dataParams.append('username', 'admin')
dataParams.append('password', 'admin')
Axios.post(URL, dataParams, {
// if you still have problems try more specific options like:
// withCredentials: true,
// crossdomain: true,
// ...
})
.then(res=>{
console.log(res)
}
)
.catch(error=>{
console.log(error)
}
)
Aside from that, the issue in your question is usually caused by CORS. If you use CORS and request an untrusted origin, then Microsoft Edge will only send the GET request and lead to the failure of other requests. You could also refer to this thread to understand why CORS requests fail in Microsoft Edge but work in other browsers. Microsoft Edge also uses Enhanced Protected Mode, the outcome is that: if the site is trusted, it will make two requests, OPTIONS and GET, but if it's not trusted, it only makes the GET request which causes it to fail.
In my case problem was caused by a self-sign certificate. As soon as I started using normal certificate everything began to work.
I have a web app(front-end angular js) that has a socket connection to my express server which works. Now i have to add another socket connection which listen to events from a different server. Can i do this ? Is there any docs i can refer to?
Please refer to socket io docs . Look up io.connect
var server1_socket = io.connect('http://192.168.1.1:3000');
var server2_socket = io.connect('http://192.168.1.1:3001');
server1_socket.on('server1_connection', function (data) {
console.log('Server 1 connection');
});
server2_socket.on('server2_connection', function (data) {
console.log('Server 2 connection');
});
You can you angular-socket-io which exposes a socket factory for instantiating sockets.
I followed the following tutorial to create a RESTApi for my node server...https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
My server file now has routes that allow it to to make GET and POST requests which I've tested on Postman and they work. My server file is pretty long but here is an excerpt to get an idea of how it works...
router.route('/bears')
// create a bear (accessed at POST http://localhost:8080/api/bears)
.post(function(req, res) {
var bear = new Bear(); // create a new instance of the Bear model
bear.name = req.body.name; // set the bears name (comes from the request)
// save the bear and check for errors
bear.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Bear created!' });
});
})
.get(function(req, res) {
Bear.find(function(err, bears) {
if (err)
res.send(err);
res.json(bears);
});
});
router.route('/bears/:bear_id')
// get the bear with that id (accessed at GET http://localhost:8080/api/bears/:bear_id)
.get(function(req, res) {
Bear.findById(req.params.bear_id, function(err, bear) {
if (err)
res.send(err);
res.json(bear);
});
});
...etc,etc
Now, since I am using an ionic framework I need to configure it to use this server as a backend.
My problem is, how do I connect to it using angular?
All my routes are prefixed using /api
app.use('/api', router);
So I tried the following...
app.factory('Bear', function ($resource) {
return $resource('http://XXX.XXX.X.XX:3000/api/bears/:bearId');
});
But I'm not sure this is working. I want to make one Post request so that I can test that the backend is working but I do not know what code to add to do so.
For example, if I have a form on my index.html and I send this info to my angular controller, how can my controller take this info and make a post request to my server? I've been trying to figure this out for days.
If you just want to test that your backend is working, check out postman.
Here's how you can refactor your code. First, note that as it is currently, how you're using $resource isn't actually make any calls to the API. You should inject your Bear service in a controller or another service somewhere in your app, depending on how you're going to use the bears. Then, in this other service or controller, you would do
var result = Bear.get({ bearId: <value> }) or var result = Bear.post({ bearId: <value> })
or whatever other http method you want to use. The resource object will then automatically hit the URL endpoint with the specified HTTP action and the parameter you have provided and then return you back the result.
Check out the $resource documentation for more detail. Also, the fact that you're using ionic has no bearing on connecting to the API.
I am currently running an express server express.js with an angular js app. I use the UI router https://github.com/angular-ui/ui-router with stateprovider and state.go.
I have a requirement to allow a url to be typed in the browser
/getEmployeeDetails/1234
Am i going along the right lines , in that the following code can be added to the express server.js to achieve this or should I be handling this in the angular app states.
app.get('/p/:empId', function(req, res) {
controller.getEmpDetaails(req.params.empId);
state.go("employeeDetailsview")
});
I am not sure what was the reason for writing angular code inside your Express server but you should really separate your client code from your server code.
I assume you are trying to get some employee details by ID from your server.
The way it is usually done is by sending a HTTP request with the ID number from your client to the server. Then, the server will process the HTTP request (Maybe get some data from the database) and return a HTTP response to the client. And then the client will process the response and do something with it.
In your client yo can do something like this:
$http.post('SERVER_URL/getEmployeeDetails/', {'id': 1234})
.then(function(response){
// Response.data will have the data returned from the server
// Do something with it. for example, go to other state and pass the data to it
state.go("employeeDetailsview", {'employee': response.data});
});
The above will request an employee with id 1234 and do something with it.
In the server side:
app.post('getEmployeeDetails/', function(req, res) {
var employeeId = req.body.id; // YOU SHOULD USE THE BODY-PARSER MODULE IN ORDER FOR THIS TO WORK.
....
// Do something with ID
....
// Return some data to the client - for example an employee object
res.status(200).json({'data': employeeObject});
});
I can't connect to socket.io in production. It works fine in my dev server, but I'm not getting the "websocket user connected" message in the console in production and my heat map isn't populating with the test data. I'm getting net:: ERR_CONNECTION_TIMED_OUT in the browser jscript console.
from the server:
io.origins('http://example.com/path:8080')
app.get('/somepath', function (req, res, next) {
// code here
io.emit('update', data)
console.log('update has been emitted') // this prints and I see the data object in the console
res.end("OK")
})
io.on('connection', function (socket) {
console.log('websocket user connected')
});
from the angular controller:
$http.get('http://example.com/somepath?'+str) // hits somepath with test data in query string 'str'
from the script in /path:
var socket = io('http://example.com:8080');
and I've also included the cdn for socket.io in the page /path
<script src="https://cdn.socket.io/socket.io-1.3.2.js"></script>
The problem was that I had to include to port number in the URL for the development server, but it will not make the connection if I use the port in my production server. I'm not sure exactly why this is, but I suppose that the port is implied in a request from my browser and maybe something about the format makes it unrecognizable if explicitly stated.
Changes I made:
I removed the io.origins statement from the server because the default for socket.io is to allow any origin. That removes one possible source of error.
I removed the port number from $http.get() in the angular controller and changed var socket = io('http://example.com:8080') to var socket = io('http://example.com') in another script