3

As of yesterday nginx started to support websocket connections, therefore i was trying to get my nginx-nodejs-socket.io application to work without harproxy ect (not much luck though).

What i want exactly to achieve is nginx to send only websocket connection requests to a backed server,or websocket server ,socket.io to be more exact, while in the same time nginx will be serving php files, and all static content including html files.I dont want express to serve static content at all (if this is possible).

Here is my nginx.conf

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;

    upstream backend {
        server 127.0.0.1:8080;
    }

    server {
        listen       80;
        server_name  localhost;

        charset UTF-8;

        #access_log  logs/host.access.log  main;

        location / {
            root   /website/html_public;
            index  index.php index.html index.htm;
        }       
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /website/html_public;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        location ~ \.php$ {
        root           /website/html_public;
        try_files      $uri =404;
        fastcgi_pass   unix:/tmp/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        location ~ /\.ht {
            deny  all;
        }

         location /connection {
         proxy_pass http://backend;  
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "upgrade";
             }
       }

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   /website/html_public;
    #        index  index.php index.html index.htm;
    #    }
    #}
}

Here is my server.js file in node

var express = require('express');
var app     = express();
var port    = 8080;

/* HTTP Server*/

server = require('http').createServer(app);
server.listen(port);
app.use(express.logger(':remote-addr - :method :url HTTP/:http-version :status :res[content-length] - :response-time ms'));
app.use(express.static(__dirname + '/html_public'));
app.use(express.favicon());

app.set('view engine', 'jade');
app.set('view options', { layout: false });
app.set('views', __dirname + '/views');

app.get('/', function(req, res){
    res.render('index.html');

});

/*
* Web Sockets
*/
io   = require('socket.io').listen(server),
io.configure('production', function(){
io.enable('browser client etag');
io.set('log level', 1);
io.set('transports', [ 'websocket', 'htmlfile', 'xhr-polling', 'jsonp-polling' ]);
});


console.log('Chat Server started with Node '+ process.version +', platform '+ process.platform + 'to port %d',port); 

From my client, i try to connect like this :

socket = new io.connect('http://localhost/connection');

Now, the problem is that when i try to connect normally, typing localhost, i see on chrome console: **GET http://localhost/socket.io/socket.io.js 404 (Not Found)** , and also when type in the browser http://localhost/connection i receive "Cannot GET /connection" which is telling me that nginx doesn't proxy websockets normally with my current configuration.

Thanks in advance for your answers.

Skeptic
  • 1,254
  • 14
  • 18
  • 2
    Why you want to serve static content through Apache? It is an overhead. Nginx can also do it well [see this question](http://stackoverflow.com/questions/869001/how-to-serve-all-existing-static-files-directly-with-nginx-but-proxy-to-apache) for example – Mustafa Feb 20 '13 at 20:44
  • @Mustafa You misunderstood i don't want Apache to do anything cause simply is not present in my project, i use only Nginx, i think you didn't read my question carefully, i showed my nginx.conf file. – Skeptic Feb 21 '13 at 01:21
  • 1
    Does your backend respond to `GET /connection` requests? Do you have `/website/html_public/socket.io/socket.io.js` file on your server? – VBart Feb 21 '13 at 17:07
  • @VBart No my backed doesnt respond to GET /connection requests,i have socket.io.js on the server, but it loads only when i type localhost:8080 , when simply type localhost is failing to load the resource (cause nginx doesnt proxy the websocket i assume) – Skeptic Feb 22 '13 at 11:31
  • But you don't configure nginx to proxy on `localhost:8080`. Instead you have configured nginx to proxy on `localhost:8080/connection`. What happens if you type `localhost:8080/connection`? – VBart Feb 22 '13 at 11:46

2 Answers2

1

Let me guess, you want:

location /connection {
    proxy_pass http://backend/;
    ...
}

but you have:

location /connection {
    proxy_pass http://backend;
    ...
}

http://nginx.org/r/proxy_pass

VBart
  • 14,714
  • 4
  • 45
  • 49
  • I changed the nginx config as you proposed, but i still receive the "Cannot GET /connection" message when i type "localhost:8080/connection".I noticed when i type only the ip in my browswer, socket.io cant be loaded, but it loads correctly when type ip:8080.Maybe its my server.js fault, and nginx interfere with express serving the socket.io.js file?Im lost! – Skeptic Feb 22 '13 at 17:03
  • Do you still see `GET http://localhost/socket.io/socket.io.js 404 (Not Found)` in Chrome console? – VBart Feb 22 '13 at 17:14
  • Unfortunately yes.Only when i point browser to localhost:8080 (and from client also localhost:8080) , socket.io.js is resolved normally :/ – Skeptic Feb 22 '13 at 17:35
  • Is `socket.io.js` located in `/website/html_public/socket.io/` directory? – VBart Feb 22 '13 at 17:40
  • socket.io.js is being called as follows from index.html : And when rendered its source is localhost:8080/socket.io/socket.io.js ,is dynamically called from socket.io it self, you think i should call it "directly" and included it in my scripts folder instead? – Skeptic Feb 22 '13 at 19:57
  • 1
    `src="./socket.io/socket.io.js"` exactly means that browser must load this script from server. There's no magic. – VBart Feb 22 '13 at 20:58
  • Ok there is some improvement now,when i hit localhost:8080/connection (or just localhost) i receive a responce, the client is connected to the socket.io server, i see the handshake in console, but it keeps saying "connecting...", also when i try to send messages it wont actually send them,i see only heartbeats and stuff in console,what can be wrong? (no errors in chrome console) – Skeptic Feb 22 '13 at 22:04
  • Sorry, it's out of my competence. From nginx side it seems all working now, but I'm not familiar with node.js. – VBart Feb 22 '13 at 22:37
-1

Just to make sure, do you have Nginx version 1.3.13 ? ( ex. Nginx's PPA don't have that version yet.)

El Toro
  • 19
  • 3
  • yes i compiled it yesterday, here is the link for anyone interested http://nginx.org/download/nginx-1.3.13.tar.gz – Skeptic Feb 21 '13 at 13:49