2

In a mobile app that I developing I use WebSockets to subscribe/publish a range of different information. In most instances the app side websocket is simply a listener. However, there are times when it does also publish a message.

Server side I am handling this using a combination of [NChan][1] working on top of Nginx. One of the really nice features of NChan is the ability to "multiplex" a websocket - i.e. have it pub/sub on multiple channels. When creating a mobile app this goes a long way to improving tidiness and battery friendliness.

As explained in the [NChan documentation][2] I have set up multiplexed pubsubchannels

location ~ /pubsub/(\w+)/(\w+)/(\w+)/(\w+)/(\w+)$ 
{
 nchan_pubsub;
 nchan_channel_id "$1" "$2" "$3" "$4" "$5" "control";
 nchan_publisher_upstream_request /alter;
}

The third line above, chan_publisher_upstream... forwards incoming pubrequests to another server

location = /alter 
{
 proxy_pass https://example.com;
 proxy_set_header X-Publisher-Type $nchan_publisher_type;
 proxy_set_header X-Prev-Message-Id $nchan_prev_message_id;
 proxy_set_header X-Channel-Id $nchan_channel_id;
 proxy_set_header X-Original-URI $request_uri;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";
} 

On the other server I have set up Nginx to run PHP with index.php in the server root folder reading

<?php
 trigger_error(json_encode(getallheaders()));//a test to see that the proxy pass is actually 
 happening
 
 header("HTTP/1.1 304 Not Modified");
 //if successful should cause the incoming request to be published without changes
 
 //header("HTTP/1.1 204 No Content");
 //when enable will suppress the incoming request (optionally after doing some server-side
 //stuff with the incoming request data

 //header("HTTP/1.1 200 OK"); 
 //echo 'New Content!';
 //when enabled should replace the incoming requestt content with the new one 
 ?>

As far as I can tell I have followed the NChan instructions quite diligently. However, when I attempt to use this configuration to publish on the now defined pubsub channel the client connection is unexpectedly being closed down. To perform this test I am using some simple JavaScript

    var socket;

    function connectPubSub()
    {
     socket = new WebSocket("wss://app.server.url/pubsub/personal/cause/beacon/grid/chat");
     socket.onopen = whenOpen;
     socket.onmessage = whenMessage;
     socket.onclose = whenClose;
     socket.onerror = whenError;
    } 

    function whenOpen(e){console.log("[open] Connection established");}

    function whenMessage(event){console.log(`[message]:${event.data}`);}

    function whenClose(event) 
    {
     if (event.wasClean) 
      alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
      else console.log('[close] Connection died');
    }

    function whenError(error){console.log(`[error] ${error.message}`);}

    function sendMessage(msg){socket.send(msg);}

At this point when I try to issue the following

connectPubSub();
sendMessage('Hello world!');

I get the output shown below

[open] Connection Established
Websocket connection to app.server.url failed:Close received after close

The error event is as shown below

bubbles: false
cancelBubble: false
cancelable: false
composed: false
currentTarget: WebSocket {url: "wss://app.server.url/pubsub/personal/cause/beacon/grid/chat", 
readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
defaultPrevented: false
eventPhase: 0
isTrusted: true
path: []
returnValue: true
srcElement: WebSocket {url: "wss://app.server.url/pubsub/personal/cause/beacon/grid/chat", 
readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
target: WebSocket {url: "wss://app.server.url/pubsub/personal/cause/beacon/grid/chat", 
readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
timeStamp: 83208.4250000189

This has me stumped. I thought I would simply be able to follow the NChan docs and publish messages on the multiplexed pubsubchannel, then examine the message content (JSON) on my proxy server prior to deciding what to do

  • Let the message through (issue an HTTP 304)
  • Take server-side action & then suppress the message (issue an HTTP 204)
  • Modify the message and send it on (issue an HTTP 200)

My rather sketchy knowledge of Nginx configuration directives is probably letting me down here. What am I doing wrong?


I have now been able to establish what is going on here. The root of the problem here appears to bee the

proxy_pass https://example.com;

directive. If I change it to

proxy_pass https://example.com/index.php;

things work as expected. However, it is still not clear to me why this might be happening. The top of my Nginx default configuration file has the lines

server 
{
 root /path/to/root;
 index index.php;

 server_name example.com;

I thought the third line above, index index.php is pretty much all I need to tell Nginx to execute index.php at any folder/subfolder location. Clearly, not the case? [1]: https://nchan.io [2]: https://nchan.io/#getting-started

1
  • No, that does not work.
    – DroidOS
    Sep 1 '20 at 4:50

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.