SQLite y el error “attempt to write a readonly database”

Este error es la seguna vez que viene a morderme el culo, hace poco fue con nginx, que se emperraba en decir que no podía leer el fichero index.html de un bloque.

La solución en ambos casos es la misma, así que a ver si escribiéndola me la consigo aprender: no basta con tener permisos en el propio fichero, la carpeta que los contiene tiene que tener el permiso de escritura.

Edición de cinco minutos después: acabo de caer en la cuenta de que en las instrucciones de una clase que subí a Github hace cinco años (phpLoginBlacklist) especifico claramente:

 It is recommended to provide a path outside the web document root (remember to give write permissions on that folder to your web server user).

Así que queda demostrado que en lo referente al sistema de ficheros de Linux mi memoria es equivalente a la del pez Dory. 🤦‍♂️

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;