Cannot get data from SG websocket changes-feed

Hi, I’m trying to use Websockets to get a changes-feed from the Sync Gateway.

It works okay when I use regular HTTP using GET /{db}/_changes, but I don’t get any data when using a websocket-feed using GET /{db}/_changes?feed=websocket

I’m running Sync Gateway 1.3.1-16 on localhost (Ubuntu 16.04 4.4.0-42-generic x86_64)
I tried connecting to the websocket using JavaScript served by an Apache-instance on localhost (Apache 2.4.18-2ubuntu3.1) and through a Chrome-plugin (Smart WebSocket Client).

Both my JavaScript and Chrome-plugin work fine when I’m using a simple Python-script to simulate a WebSocket server.
Any idea what’s going on?

Thanks,
Vincent

This is a snippet from the SG log:

2016-10-24T17:14:59.729+02:00 HTTP:  #5377: GET /swft/_changes?feed=websocket  (ADMIN)
2016-10-24T17:14:59.729+02:00 HTTP+: #5377:     --> 101 Upgraded to WebSocket protocol  (0.0 ms)
2016-10-24T17:15:13.657+02:00 Changes+: Notifying that "sync_gateway_swft" changed (keys="{*, aln-lx911653_aron_json}") count=128
2016-10-24T17:15:13.657+02:00 Changes+: MultiChangesFeed: channels expand to channels.TimedSet{"*":channels.VbSequence{VbNo:(*uint16)(nil), Sequence:0x2ac7}, "!":channels.VbSequence{VbNo:(*uint16)(nil), Sequence:0x1}} ... 
2016-10-24T17:15:13.657+02:00 Changes+: MultiChangesFeed: channels expand to channels.TimedSet{"!":channels.VbSequence{VbNo:(*uint16)(nil), Sequence:0x1}, "*":channels.VbSequence{VbNo:(*uint16)(nil), Sequence:0x2ac7}} ... 
2016-10-24T17:15:13.657+02:00 Changes+: Notifying that "sync_gateway_swft" changed (keys="{*}") count=129
2016-10-24T17:15:13.657+02:00 Changes+: Sending seq:18196 from channel *
2016-10-24T17:15:13.657+02:00 Changes+: Sending seq:18197 from channel *
2016-10-24T17:15:13.657+02:00 Changes+: Sending seq:18196 from channel *
2016-10-24T17:15:13.657+02:00 Changes+: Sending seq:18197 from channel *

And the config:

{                                                                                                                                                                                                                                                  
        "log": ["HTTP+", "Changes+"],                                                                                                                                                                                                              
        "adminInterface": "127.0.0.1:4985",
        "interface": "0.0.0.0:4984",
        "CORS": {
                "Origin": ["http://localhost:8080"],
                "LoginOrigin": ["http://localhost:8080"],
                "Headers": ["Content-Type"],
                "MaxAge": 1728000
        },
        "databases": {
                "swft": {
                        "unsupported": {
                                "user_views": {
                                        "enabled":true
                                },
                                "oidc_test_provider": {
                                        "enabled":false
                                }
                        },
                        "server": "http://<hostname>:8091",
                        "bucket": "sync_gateway_swft",
                        "sync": "function(doc){if(doc.type == \"some_type\"){channel(\"some_type\");}else{channel(doc.host_id);}}",
                        "users": {
                                "GUEST": {"disabled": false, "admin_channels": ["*"]}
                        }
                }
        }
}

Following is a snippet of the JavaScript code I’m using:

var ws = new WebSocket("ws://localhost:4985/swft/_changes?feed=websocket");

ws.onopen = function(){  
    console.log("Socket has been opened!");  // This works, socket seems opened okay

};

ws.onmessage = function(event) {
    console.log("MESSAGE");
    console.log(event);
};

ws.onerror = function(event) {
    // No errors are shown
    console.log("ERROR: ");
    console.log(event);
}

// WebSocket-object looks okay at this point. 
// ws.readyState == 1, meaning the connection is open and ready to communicate.
console.log(ws); 

From the Sync Gateway log provided, it looks like it’s upgrading to websocket and sending changes as expected.

Have you tried adding logging in ws.onclose to see if the websocket connection is being closed before the data from Sync Gateway arrives?

SG is waiting for the feed parameters; you have to send those as a JSON object in your first WebSocket message (the same format as with a POST to _changes.) After that everything will function as expected.

Thanks, sending the feed-parameters solved my issue :grinning:

Turns out you need to have the ?feed=websocket parameters appended to the URL, and send your other parameters as JSON after the socket has opened (sending an empty JSON-object if no parameters are used).

I might have looked in the wrong places, but I couldn’t find any documentation about this… Maybe it’s a good idea to add this to the API-docs?

Attn @jamiltz :slight_smile: Can we add this to the Swagger spec, or are WebSockets out of scope for that?