we are trying to connect to a geth node via WebSockets to be able to subscribe to contract events. This node is created with docker and this docker uses nginx as a proxy.

We can connect easily with http (not WS rpc), but we cannot subscribe to contract events with http.

We have managed to establish the connection in a local instance of this docker image with a nodejs websocket server with this same nginx proxy. But we cannot connect with web3 v1.0.0-beta55.

The 2 different error we get are 403 (Forbidden) with this nginx config (which is the one that works with non web3 websockets):

location /rpcws {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_pass http://localhost:22001;

or error 400 (bad request) with this other configuration:

location /rpcws {
    proxy_pass http://localhost:22001;

On the client side we get either

Error during WebSocket handshake: Unexpected response code: 400||403


connection not open on send()

Right now we are tracking possible port issues, in a local instance of this docker image, but we have configured several times the node to receive this ws connection through the already working http rpc port (Obviously changing all the geth and nginx config to receive wsrpc and not http rpc) and we get the same error codes.

Our main guess is that nginx is not proxy_passing correctly the WebSocket request. We asked the quorum network technical team and they have never tried to establish a WebSocket connection, and they don't know how to help us any further. Any guess is well received.


All the code is listed below.

Solidity smart contract:

pragma solidity 0.4.18;

contract EventTest {

   string fName;
   uint age;

   event doSetInstructor();
   event instructorSetted(string name, uint age);

   function askForSetInstructor() public {

   function setInstructor(string _fName, uint _age) public {
       fName = _fName;
       age = _age;
       instructorSetted(fName, age);

   function getInstructor() public constant returns (string, uint) {
       return (fName, age);


Web3 connection:

var Web3 = require('web3');
var TruffleContract =  require('truffle-contract');
var eventTestABI = require('./abi/EventTest.json');
var io = require('socket.io-client');

var web3 = new Web3(new Web3.providers.WebsocketProvider('ws://'));

var contractAddress;

web3.eth.defaultAccount = '0x41E4e56603bF37a03Bb5Asa635787b3068052b82';

let truffleContract = TruffleContract(eventTestABI);
contractAddress = '0x82ce1df01f2a8bcadfad485eaa785424123734f7';
let contract = new web3.eth.Contract(eventTestABI.abi, contractAddress, {
    from: '0x41E4e56603bF37a03Bb5Asa635787b3068052b82',
    gas: 20000000,
    gasPrice: 0,
    data: truffleContract.deployedBytecode

web3.eth.subscribe('logs', {
    address: contract.options.address,
    topics: [contract.events.doSetInstructor().signature]
}, (error, result) => {
    if (!error) {
        console.log("Event triggered");
        const eventObj = web3.eth.abi.decodeLog(
        console.log("New event!", eventObj)
        console.log("Error watching event", error);

The geth set up:

--networkid $NETID --identity $IDENTITY --permissioned --ws --wsaddr 
--wsport 22001 --wsapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,
istanbul --wsorigins '*' --rpc --rpcaddr $RPCADDR --rpcapi admin,db,eth,debug,miner,
net,shh,txpool,personal,web3,quorum,istanbul --rpccorsdomain '*' --rpcport 22000
--port 21000 --istanbul.requesttimeout 10000  --ethstats $IDENTITY --verbosity 3 --vmdebug --emitcheckpoints --targetgaslimit 18446744073709551615 --syncmode full --gcmode $GCMODE --vmodule consensus/istanbul/core/core.go=5 --nodiscover

The nginx conf file:

limit_req_zone $binary_remote_addr zone=one:10m rate=999999999999999999r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;

client_body_buffer_size 128k;

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    root /var/www/html;
    access_log /var/log/nginx/access_log combined;
    error_log /var/log/nginx/error.log warn;
    index index.html index.htm index.nginx-debian.html;
    #ssl_certificate /etc/ssl/nginx/alastria-test.crt;
    #ssl_certificate_key /etc/ssl/nginx/alastria-test.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;
    client_body_timeout 30s;
    client_header_timeout 30s;

    add_header 'Access-Control-Allow-Headers' 'Content-Type';
    add_header 'Access-Control-Allow-Origin' "http://someurl.com";  

    location / {
        # First attempt to serve request as file, then as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    location /rpcws {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://localhost:22001;
    location /rpc {
        # Request rate and number of connections limitation
        limit_req zone=one burst=30 nodelay;
        limit_conn addr 10;
        # Whitelist/Blacklist
        include ./conf.d/blacklist;
        content_by_lua_block {
            local data = ngx.req.get_body_data()
            if data then
                if not (string.match(data,"eth_") or string.match(data,"net_") or string.match(data,"web3_") or string.match(data, "personal_")) then

    location @rpc_proxy {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_pass http://localhost:22000;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.