
Em um aplicativo móvel que desenvolvo, utilizo WebSockets para assinar/publicar uma série de informações diferentes. Na maioria dos casos, o websocket do lado do aplicativo é simplesmente um ouvinte. No entanto, há momentos em que também publica uma mensagem.
Lado do servidor, estou lidando com isso usando uma combinação de [NChan] [1] trabalhando em cima do Nginx. Um dos recursos realmente interessantes do NChan é a capacidade de "multiplexar" um websocket - ou seja, pub/sub em vários canais. Ao criar um aplicativo móvel, isso ajuda muito a melhorar a organização e a facilidade de uso da bateria.
Conforme explicado na [documentação do NChan] [2] eu configurei pubsub
canais multiplexados
location ~ /pubsub/(\w+)/(\w+)/(\w+)/(\w+)/(\w+)$
{
nchan_pubsub;
nchan_channel_id "$1" "$2" "$3" "$4" "$5" "control";
nchan_publisher_upstream_request /alter;
}
A terceira linha acima chan_publisher_upstream...
encaminha solicitações recebidas pub
para outro servidor
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";
}
No outro servidor eu configurei o Nginx para rodar o PHP na index.php
leitura da pasta raiz do servidor
<?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
?>
Pelo que posso dizer, segui as instruções do NChan com bastante diligência. No entanto, quando tento usar esta configuração para publicar no pubsub
canal agora definido, a conexão do cliente é encerrada inesperadamente. Para realizar este teste estou usando um JavaScript simples
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);}
Neste ponto, quando tento emitir o seguinte
connectPubSub();
sendMessage('Hello world!');
Eu recebo a saída mostrada abaixo
[open] Connection Established
Websocket connection to app.server.url failed:Close received after close
O evento de erro é mostrado abaixo
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
Isso me deixou perplexo. Achei que seria simplesmente capaz de seguir os documentos do NChan e publicar mensagens no pubsub
canal multiplexado e, em seguida, examinar o conteúdo da mensagem (JSON) no meu servidor proxy antes de decidir o que fazer
- Deixe a mensagem passar (emitir um HTTP 304)
- Execute uma ação no servidor e suprima a mensagem (emitir um HTTP 204)
- Modifique a mensagem e envie-a (emitir um HTTP 200)
Meu conhecimento um tanto superficial das diretivas de configuração do Nginx provavelmente está me decepcionando aqui. O que estou fazendo de errado?
Agora consegui estabelecer o que está acontecendo aqui. A raiz do problema aqui parece ser a
proxy_pass https://example.com;
diretiva. Se eu mudar para
proxy_pass https://example.com/index.php;
as coisas funcionam como esperado. No entanto, ainda não está claro para mim por que isso pode estar acontecendo. A parte superior do meu arquivo de configuração padrão do Nginx contém as linhas
server
{
root /path/to/root;
index index.php;
server_name example.com;
Achei que a terceira linha acima index index.php
é praticamente tudo que preciso para dizer ao Nginx para executar index.php em qualquer local de pasta/subpasta. Claramente, não é o caso? [1]:https://nchan.io
[2]:https://nchan.io/#getting-started