I am using node js express with socket.io and apache for my reverse proxy. Below is my reverse proxy configuration.
ProxyPass /chatApp http://localhost:3000/
ProxyPassReverse /chatApp http://localhost:3000/
So, my application will be accessed by https://server.com/chatApp. Below is how socket is defined in my html.
var socket = io("https://server.com/chatApp")
The browser throws the following error.
GET https://server.com/socket.io/?EIO=3&transport=polling&t=M9zVwUq 404 (Not Found)
But, when I hit the below URL in the browser, I am getting some results.
https://server.com/chatApp/socket.io/?EIO=3&transport=polling&t=M9zVwUq
Even though, I have mentioned /chatApp in my html (while defining socket variable), my application is not calling server.com/chatApp/socket.io/?EIO..... It's skipping chatApp in the URL, and just calling server.com/socket.io/?EIO...
I've tried the solution to this post. No luck.
In socket.io's io() interface, the path you pass there is not used as the path on the URL. It's used as the namespace you want to connect to. If you want to specific a custom path, you need to use a separate argument:
var socket = io("https://server.com", {path: "/chatApp/socket.io"});
If this still isn't giving you exactly what you want, then examine what URL socket.io is using (look in the network tab of the Chrome debugger to see it) and then adjust the path argument accordingly.
Here's the socket.io documentation reference for the path option: https://github.com/socketio/socket.io-client/blob/master/docs/API.md#with-custom-path.
Note the /socket.io part of the path is required so the server can properly identify socket.io requests.
Related
I have an app set up using BackboneJS, NodeJS and ExpressJS. I have trouble accessing my routes from my application. But I can access my routes directly in my browser and see the output.
For example this works:
http://test.myserver.com:3000/employees/1
(where test.myserver.com is my server address accessible externally)
My express server declaration is as follows:
var express = require('express'),
employee = require('./routes/employees');
var app = express();
app.get('/employees/:id', employee.findById);
app.listen(3000);
My problem is that when I try to access the route through my application I get an access error.
http://test.myserver.com/pages/index.html#employees/1
GET http://localhost:3000/employees/1?callback=jQuery19107984810129273683_1457829695460&_=1457829695461 net::ERR_CONNECTION_REFUSED
How can I access my routes from within my application using Express?
I see an issue. You say you're loading a web page at:
http://test.myserver.com/pages/index.html#employees/1
But, the URL request is for:
http://localhost:3000/employees/1?callback=jQuery19107984810129273683_1457829695460&_=1457829695461
Those are different domains and different ports. It looks to me like jQuery sees that this is a cross origin request and is trying to turn it into a JSONP request, but your server is not support JSONP.
Likely what you need to do is to get the Javascript in your web page to be requesting the SAME origin (same domain, same port) that the web page is loaded from. Then, it will not be cross origin request and it should work (if nothing else is wrong).
Please show us the relevant Javascript in your web page that is making this request so we can advise more specifically on how to fix it.
Also, if you're expecting your node.js server to serve your web pages, you will need node.js code to do that (you don't show any of that code) since node.js does not serve any pages by default (unlike some other web servers).
There is a feature in a tool called charles that allows you to map remote requests:
http://www.charlesproxy.com/documentation/tools/map-remote/
Basically, it can take any request to a server(even if you're not the one running it) and then makes a new request to another server, preserving the path and the query string. The response from the second server then overwrites the response from the first server.
I just want to know if there is a node module that can do this. I tried using http-proxy, but I have a feeling this map remote tool is a bit different than a proxy, since it seems like you must own both servers with a proxy.
EDIT: Tried using the http-proxy node module again, but can't seem to get it to work. Here's my code:
var http = require('http')
, httpProxy = require('http-proxy');
httpProxy.createServer({
hostnameOnly: true,
router: {
'www.stackoverflow.com': 'localhost:9000',
}
}).listen(80);
// Create your target server
//
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
res.end();
}).listen(9000);
My expectation is that when I go to www.stackoverflow.com or www.stackoverflow.com:80, it will instead redirect to my localhost:9000
No, what you are asking for is indeed a simple proxy. And no, you don't have to "own" both servers to run a proxy. You simply proxy the request, and at that point you can modify the data however you wish.
The proxy module you mention will work fine, and there are many others. You can also do this with simple Nginx config if you wish.
I made this pastebin with my solution:
http://pastebin.com/TfG67j1x
Save the content of the pastebin as proxy.js. Make sure you install dependencies in the same folder as the proxy.js file. (npm install http-proxy colors connect util --save)
When you run the proxy, it will:
start a new server listening on 8013, acting as a proxy server;
start a demo target server listening at 9013.
When accessing the demo target through the proxy, it modifies the "Ruby" string into "nodejitsu", for easy testing. If you are behind a corporate firewall/proxy, this script fails for now.
UPDATE: The problem with "headers already sent" was at line 32/33. It turns out that several errors occured on the same connection. When first error occurs, headers would be sent, when second error occurs, headers are already sent; as a result a "headers already sent" exception is raised and the server is killed.
With this fix the server no longer dies, but it still does not fix the source of the error, which is that NODE.JS cannot reach your target site. You must be behind another proxy/firewall and NodeJS would need to forward the HTTP request to a second proxy. If you normally use a proxy in your Browser to connect to Internet, my solution will fail. You did not specify this to be a requirement, though.
You may verify this by accessing through my proxy a server inside your network (no proxy required for it normally).
UPDATE2: You should not try to access http://localhost:8013 directly, but to set it as a proxy in your browser. Take notice of your original browser proxy settings (see above). Try and access then http://localhost:9013.
Did you add that proxy to your browser config? Otherwise the underlying OS would route your request directly to www.stackoverflow.com and there is no way your proxy is catching that.
Could you confirm that www.stackoverflow.com is ending up at your node.app at all? The name currently will resolve to the IP address that leads you to this website, so you would have to have made sure that name now resolves to your node.app. In this case, that probably means editing your hosts file.
I have a working node.js Express server to which I would to add socket.io support (allow javascript clients to connect via socket.io). I can connect to the express server via a Javascript $.get(), but the socket.io.connect() command fails due to a CORS error.
My testing machine is OSX with Apache to serve the client, thus port 80 is taken, so I have node.js/express running on port 8888. I added socket.io per the documentation:
var exp = express();
var server = require('http').createServer(api.server);
exp.listen(8888);
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
console.log('connection');
});
I properly see "info: socket.io started" in my node.js logs.
Then, on the client, I attempt to connect to the server...
this.socket = io.connect('http://localhost:8888');
this.socket.on('connect',function() {
socket.emit('install','test');
});
However, I'm getting a CORS error in the console in Chrome:
XMLHttpRequest cannot load http://localhost:8888/socket.io/1/?t=1358715637192. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
HOWEVER, THIS works fine!
$.get('http://localhost:8888',function(e,d){
console.log(e,d);
});
So I double checked my headers, for both localhost:8888 and localhost -- both are properly returning the headers which (should) allow for the cross-domain requests...
Access-Control-Allow-Origin: *
Any ideas?
CORS is a very tricking thing to get working (or at least it was for me). I recommend this resource here: http://enable-cors.org/
Following what they do very carefully helped me. I also found that different browsers gave different visibility over the CORS request/responses which helped.
I found that Chrome was easier to get working than firefox, but firefoxes tools such as firebug, were quite nice to work with.
My gut feel from your information is that you might need your request to have an X-Request-With in your request attributes.
I also found using fidler to send the http requests allowed me to narrow my problems down to the server side initially and get that working. You will find browser enforce CORS, but something like fidler doesn't and thus provides another way of inspecting what is happening.
I definately recommend trying to break the problem in half so that you can see if it is server side or client side that is not behaving how you expect.
My problem was related to returning the same CORS response for the OPTIONS header as the POST or GET. That was wrong. Chrome allowed it. Firefox didnt. Any options request that is sent out will be sent out once, then in the future it will be cached and not resent (Which caused alot of confusion for me initially). For the options request you just need a standard response saying its ok to proceed, then in the post or get response i believe you want your cors responses there only.
I am using :
"socket.io": "~0.9.10"
I am running into this issue when I go to my apache webserver hosted client.html page hosted on port 80:
XMLHttpRequest cannot load http://localhost:5000/socket.io/1/?t=1348624895534. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
I am running SocketIO on my serverside to be on port 5000 as shown below:
io = io.listen(5000);
io.set("origins","*");
However, everytime I load my apache client.html page, I see in my SocketIO server console:
warn: illegal origin: http://localhost
How do I get rid of this issue?
You are doing CORS.
The error you are getting comes from the fact that Socket.IO seems to be using XHR rather that Websockets. This is what socket.IO does when websockets are not available it uses another protocol, FlashSockets, XHR-polling... etc.
You need to set a header on you apache server to allow a query to be made to another website, here your Socket.io server.
Here is a how to.
It would be a lot simpler for you if you just used only one server.
You could use Express to deliver the static html file. Here is a demo/tutorial app to get started easily with Socket.IO + Express.
This demo is a boiler plate to push on dotCloud, so if you want to painlessly deploy, follow those instructions.
Try setting 'Access-Control-Allow-Origin' header to '*'
response.writeHead(200, {
'Access-Control-Allow-Origin': '*'
});
For a few days we'r trying to integrate drupal with node.js. but we couldn't connect with socket.io.js..
we're getting this error message from chrome console;
XMLHttpRequest cannot load http://mydomainname.com:8080/socket.io/1/?t=1340201859161. Origin http://mydomainname.com is not allowed by Access-Control-Allow-Origin.
and our backend settings are;
/**
* This configuration file was built using the 'Node.js server configuration builder'.
* For a more fully commented example see the file nodejs.config.js.example in the root of this module
*/
backendSettings = {
"scheme":"http",
"host":"mydomainname",
"port":8080,
"key":"/path/to/key/file",
"cert":"/path/to/cert/file",
"resource":"/sites/all/modules/nodejs/node_modules/socket.io/lib",
"publishUrl":"publish",
"serviceKey":"",
"backend":{
"port":80,
"host":"urb5.com",
"messagePath":"realtime"},
"clientsCanWriteToChannels":false,
"clientsCanWriteToClients":false,
"extensions":["nodejs.server.extension.js"],
"debug":true,
"transports":["websocket",
"flashsocket",
"htmlfile",
"xhr-polling",
"jsonp-polling"],
"jsMinification":true,
"jsEtag":true,
"logLevel":1};
and also, in source code we have a script socket.io script,
like
<script type="text/javascript" src="http://mydomainname.com:8080/sites/all/modules/nodejs/node_modules/socket.io/lib/socket.io.js"></script>
this scripts build number is 0.9.6, but if we follow this path in ftp, there is a socket.io.js but its build number is 0.9.5
any suggestions?,
thanks..
The problem here, is that you are trying to load up socket.io from the server, but your front-end files are located in another domain space / server.
There is security regulations that does not allows cross-domain ajax and resources requests if they are not enabled by server.
So on server side where socket.io.js is coming from, you should add in page header something like this:
Access-Control-Allow-Origin: http://hello-world.example
Access-Control-Max-Age: 3628800
Access-Control-Allow-Methods: PUT, DELETE
This will allow you to share resource content with specified domain. And browser will not throw Access-Control-Allow-Origin error anymore.
As well, why you are trying to include js file through port 8080? If this is port that you bind your socket.io listener, then this is wrong, and you need to get js file through usual port (in most cases without defining, or 80).