Proxy inverso para websockets de socket.io con nginx

Si tenemos configurado y funcionando un servidor web podemos añadirle capacidades de websockets sin tener que complicarnos con nuevos puertos, certificados de seguridad, etc.

Para eso vamos a usar nginx como proxy inverso. En mi caso necesitaba poder conectar a un programa escrito en node mediante websockets (desde el navegador del cliente) y mediante http (desde mi API en el servidor).

El programa de node usa socket.io y escucha en el puerto 1978.

Esta es la configuración que he utilizado. En el fichero nginx.conf añadimos esta directiva dentro del bloque http:

upstream websocket {
    server localhost:1978;
}

Y en el fichero de configuración de nuestro servidor, dentro del bloque server:

# Esta es la ruta que usa socket.io para escuchar conexiones de websockets
location /socket.io/ {
    proxy_pass http://websocket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}
# Esta es la ruta a la que podremos llamar desde la API.
location /fry/ {
    proxy_pass http://localhost:1978;
}

En el código JS del cliente usaremos como host de conexión de socket.io https://midominio.com y para conectar desde PHP https://midominio.com/fry/endpoint

Comparar valores con array de datos JSON en MySQL

Supongamos que tenemos en una tabla una columna a_productIds de tipo JSON que contiene un array de números y queremos listar los registros que tienen en esa columna algún valor de una lista de números.

La forma más sencilla que he encontrado es usar la función JSON_OVERLAPS que recibe dos documentos JSON y devuelve 1 si tienen en común algún par clave-valor o elemento de array (esto es lo que nos interesa aquí).

Si queremos listar los registros que tienen en a_productIds alguno de los valores 1, 2 o 3 la consulta quedaría así:

SELECT * 
  FROM tabla 
 WHERE JSON_OVERLAPS(JSON_EXTRACT(a_productIds, '$'), '[1, 2, 3]');

En ocasiones quizá necesitemos localizar arrays vacíos, esto puede hacerse con la función JSON_LENGTH:

SELECT * 
  FROM tabla 
 WHERE JSON_LENGTH(a_productIds, '$') = 0;