json - developer - ¿Cómo uso un shell-script como aplicación de host de Chrome Native Messaging?
developer chrome apps (1)
¿Cómo se procesa una llamada a la API de Chrome Native Messaging con un script bash?
Logré hacerlo con Python con este ejemplo
Claro que puedo llamar a bash
desde el código python con subprocess
, pero ¿es posible omitir python y procesar el mensaje en bash
directamente?
La parte problemática es leer el mensaje serializado JSON en una variable. El mensaje se serializa usando JSON, UTF-8 codificado y va precedido con una longitud de mensaje de 32 bits en orden nativo de bytes a través de stdin.
echo $*
solo salidas: chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/
También algo así como
read
echo $REPLY
no produce nada No hay señal del mensaje JSON. Python usa struct.unpack
para esto. ¿Se puede hacer eso en bash
?
Sugiero que no use (bash) scripts de shell como un host de mensajería nativo, porque bash es demasiado limitado para ser útil.
read
sin ningún parámetro lee una línea completa antes de terminar, mientras que el protocolo de mensajería nativa especifica que los primeros cuatro bytes especifican la longitud del siguiente mensaje (en orden de bytes nativo).
Bash es una herramienta terrible para procesar datos binarios. Una versión mejorada de su comando de read
especificaría el parámetro -n N
para detener la lectura después de N
caracteres (nota: no bytes) y -r
para eliminar algún procesamiento. Por ejemplo, lo siguiente almacenaría los primeros cuatro caracteres en una variable llamada var_prefix
:
IFS= read -rn 4 var_prefix
Incluso si supone que esto almacena los primeros cuatro bytes en la variable (¡no es así!), Entonces debe convertir los bytes a un número entero. ¿Ya mencioné que bash elimina automáticamente todos los bytes NUL? Estas características hacen que Bash sea completamente inútil por ser un host de mensajería nativo totalmente capaz.
Podría hacer frente a esta deficiencia ignorando los primeros bytes y comenzar a analizar el resultado cuando detecte un {
carácter, el comienzo de la solicitud con formato JSON. Después de esto, debe leer todas las entradas hasta que se encuentre el final de la entrada. Necesita un analizador JSON que deje de leer la entrada cuando encuentre el final de la cadena JSON. Buena suerte al escribir eso.
Generar resultados es más fácil, solo use echo -n
o printf
.
Aquí hay un ejemplo mínimo que asume que la entrada termina con a }
, la lee (sin procesar) y responde con un resultado. Aunque esta demostración funciona, recomiendo encarecidamente no usar bash, sino un lenguaje más rico (scripting) como Python o C ++.
#!/bin/bash
# Loop forever, to deal with chrome.runtime.connectNative
while IFS= read -r -n1 c; do
# Read the first message
# Assuming that the message ALWAYS ends with a },
# with no }s in the string. Adopt this piece of code if needed.
if [ "$c" != ''}'' ] ; then
continue
fi
message=''{"message": "Hello world!"}''
# Calculate the byte size of the string.
# NOTE: This assumes that byte length is identical to the string length!
# Do not use multibyte (unicode) characters, escape them instead, e.g.
# message=''"Some unicode character:/u1234"''
messagelen=${#message}
# Convert to an integer in native byte order.
# If you see an error message in Chrome''s stdout with
# "Native Messaging host tried sending a message that is ... bytes long.",
# then just swap the order, i.e. messagelen1 <-> messagelen4 and
# messagelen2 <-> messagelen3
messagelen1=$(( ($messagelen ) & 0xFF ))
messagelen2=$(( ($messagelen >> 8) & 0xFF ))
messagelen3=$(( ($messagelen >> 16) & 0xFF ))
messagelen4=$(( ($messagelen >> 24) & 0xFF ))
# Print the message byte length followed by the actual message.
printf "$(printf ''//x%x//x%x//x%x//x%x'' /
$messagelen1 $messagelen2 $messagelen3 $messagelen4)%s" "$message"
done