[comment]: # ({96feb912-d3accdff})
# 1 Objetos JavaScript adicionales

[comment]: # ({/96feb912-d3accdff})

[comment]: # ({3ede003a-ab8bd378})
### Descripción general

Esta sección describe las adiciones de Zabbix al lenguaje JavaScript implementadas con Duktape, y las [funciones globales de JavaScript](#global-javascript-functions) soportadas.

:::noteimportant
No utilice asignaciones no declaradas en el JavaScript de preprocesamiento.
Utilice `var` para declarar variables locales.
:::

[comment]: # ({/3ede003a-ab8bd378})

[comment]: # ({c73f2449-c73f2449})
### Objetos integrados

[comment]: # ({/c73f2449-c73f2449})

[comment]: # ({1dd6fb19-e5dc8dd0})
#### Zabbix

El objeto Zabbix proporciona interacción con la funcionalidad interna de Zabbix.

|Método|Descripción|
|--|--------|
|`log(loglevel, message)`|Escribe <message> en el registro de Zabbix usando el nivel de registro <loglevel> (ver el parámetro DebugLevel en el archivo de configuración).|

Ejemplo:

```default
Zabbix.log(3, "esta es una entrada de registro escrita con el nivel de registro 'Warning'")
```

Puede utilizar los siguientes alias:

|Alias|Alias de|
|-----|--------|
|console.log(object)|Zabbix.log(4, JSON.stringify(object))|
|console.warn(object)|Zabbix.log(3, JSON.stringify(object))|
|console.error(object)|Zabbix.log(2, JSON.stringify(object))|

::: noteimportant
El tamaño total de todos los mensajes registrados está limitado a 8 MB por ejecución de script.
:::

|Método|Descripción|
|--|--------|
|`sleep(delay)`|Retrasa la ejecución de JavaScript por `delay` milisegundos.|

Ejemplo (retrasar la ejecución 15 segundos):

```default
Zabbix.sleep(15000)
```

[comment]: # ({/1dd6fb19-e5dc8dd0})

[comment]: # ({e31a78fd-413974f8})
#### HttpRequest

Este objeto encapsula el manejador cURL permitiendo realizar solicitudes HTTP simples.
Los errores se lanzan como excepciones.

::: noteimportant
La inicialización de múltiples objetos `HttpRequest` está limitada a 10 por ejecución de script.
:::

|Método|Descripción|
|--|--------|
|`addHeader(value)`|Agrega un campo de cabecera HTTP. Este campo se utiliza para todas las solicitudes siguientes hasta que se borre con el método `clearHeader()`.<br>La longitud total de los campos de cabecera que se pueden agregar a un solo objeto `HttpRequest` está limitada a 128 Kbytes (incluidos los caracteres especiales y los nombres de las cabeceras).|
|`clearHeader()`|Borra la cabecera HTTP. Si no se establecen campos de cabecera, `HttpRequest` establecerá Content-Type en application/json si los datos que se envían están en formato JSON; en text/plain en caso contrario.|
|`connect(url)`|Envía una solicitud HTTP CONNECT a la URL y devuelve la respuesta.|
|`customRequest(method, url, data)`|Permite especificar cualquier método HTTP en el primer parámetro. Envía la solicitud del método a la URL con una carga *data* opcional y devuelve la respuesta.|
|`delete(url, data)`|Envía una solicitud HTTP DELETE a la URL con una carga *data* opcional y devuelve la respuesta.|
|`getHeaders(<asArray>)`|Devuelve el objeto de los campos de cabecera HTTP recibidos.<br>El parámetro `asArray` puede establecerse en "true" (por ejemplo, `getHeaders(true)`), "false" o no estar definido. Si se establece en "true", los valores de los campos de cabecera HTTP recibidos se devolverán como arrays; esto debe usarse para recuperar los valores de campos de varias cabeceras con el mismo nombre.<br>Si no se establece o se establece en "false", los valores de los campos de cabecera HTTP recibidos se devolverán como cadenas.|
|`get(url, data)`|Envía una solicitud HTTP GET a la URL con una carga *data* opcional y devuelve la respuesta.|
|`head(url)`|Envía una solicitud HTTP HEAD a la URL y devuelve la respuesta.|
|`options(url)`|Envía una solicitud HTTP OPTIONS a la URL y devuelve la respuesta.|
|`patch(url, data)`|Envía una solicitud HTTP PATCH a la URL con una carga *data* opcional y devuelve la respuesta.|
|`put(url, data)`|Envía una solicitud HTTP PUT a la URL con una carga *data* opcional y devuelve la respuesta.|
|`post(url, data)`|Envía una solicitud HTTP POST a la URL con una carga *data* opcional y devuelve la respuesta.|
|`getStatus()`|Devuelve el código de estado de la última solicitud HTTP.|
|`setProxy(proxy)`|Establece el proxy HTTP al valor "proxy". Si este parámetro está vacío, no se utiliza ningún proxy.|
|`setHttpAuth(bitmask, username, password)`|Establece los métodos de autenticación HTTP habilitados (HTTPAUTH\_BASIC, HTTPAUTH\_DIGEST, HTTPAUTH\_NEGOTIATE, HTTPAUTH\_NTLM, HTTPAUTH\_NONE) en el parámetro 'bitmask'.<br>El indicador HTTPAUTH\_NONE permite deshabilitar la autenticación HTTP.<br>Ejemplos:<br>``request.setHttpAuth(HTTPAUTH_NTLM | HTTPAUTH_BASIC, username, password)``<br>`request.setHttpAuth(HTTPAUTH_NONE)`|
|`trace(url, data)`|Envía una solicitud HTTP TRACE a la URL con una carga *data* opcional y devuelve la respuesta.|

Ejemplo:

```javascript
try {
    Zabbix.log(4, 'jira webhook script value='+value);
  
    var result = {
        'tags': {
            'endpoint': 'jira'
        }
    },
    params = JSON.parse(value),
    req = new HttpRequest(),
    fields = {},
    resp;
  
    req.addHeader('Content-Type: application/json');
    req.addHeader('Authorization: Basic '+params.authentication);
  
    fields.summary = params.summary;
    fields.description = params.description;
    fields.project = {"key": params.project_key};
    fields.issuetype = {"id": params.issue_id};
    resp = req.post('https://jira.example.com/rest/api/2/issue/',
        JSON.stringify({"fields": fields})
    );
  
    if (req.getStatus() != 201) {
        throw 'Response code: '+req.getStatus();
    }
  
    resp = JSON.parse(resp);
    result.tags.issue_id = resp.id;
    result.tags.issue_key = resp.key;
} catch (error) {
    Zabbix.log(4, 'jira issue creation failed json : '+JSON.stringify({"fields": fields}));
    Zabbix.log(4, 'jira issue creation failed : '+error);
  
    result = {};
}
  
return JSON.stringify(result);
```

[comment]: # ({/e31a78fd-413974f8})

[comment]: # ({fdd63f84-06cac1ca})
#### XML

El objeto XML permite el procesamiento de datos XML en el preprocesamiento de elementos y descubrimiento de bajo nivel y webhooks.

::: noteimportant
Para utilizar el objeto XML, el servidor/proxy debe estar compilado con soporte para libxml2.
:::

|Método|Descripción|
|--|--------|
|`XML.query(data, expression)`|Recupera el contenido del nodo usando XPath. Devuelve null si no se encuentra el nodo.<br>**expression**: una expresión XPath;<br>**data**: datos XML como cadena.|
|`XML.toJson(data)`|Convierte datos en formato XML a JSON.|
|`XML.fromJson(object)`|Convierte datos en formato JSON a XML.|

Ejemplo:

*Entrada:*

```xml
<menu>
    <food type = "breakfast">
        <name>Chocolate</name>
        <price>$5.95</price>
        <description></description>
        <calories>650</calories>
    </food>
</menu>
```

*Salida:*

```json
{
    "menu": {
        "food": {
            "@type": "breakfast",
            "name": "Chocolate",
            "price": "$5.95",
            "description": null,
            "calories": "650"
        }
    }
}
```

[comment]: # ({/fdd63f84-06cac1ca})

[comment]: # ({46c5de71-a12fbdc2})
##### Reglas de serialización

La conversión de XML a JSON se procesará de acuerdo con las siguientes reglas (para las conversiones de JSON a XML se aplican las reglas inversas):

1\. Los atributos XML se convertirán en claves cuyos nombres estarán precedidos por '@'.

Ejemplo:

*Entrada:*

```xml
<xml foo="FOO">
  <bar>
    <baz>BAZ</baz>
  </bar>
</xml>
```

*Salida:*

```json
{
  "xml": {
    "@foo": "FOO",
    "bar": {
      "baz": "BAZ"
    }
  }
}
```

2\. Los elementos autocontenidos (<foo/>) se convertirán como si tuvieran el valor 'null'.

Ejemplo:

*Entrada:*

```xml
<xml>
  <foo/>
</xml>
```

*Salida:*

```json
{
  "xml": {
    "foo": null
  }
}
```

3\. Los atributos vacíos (con valor "") se convertirán como si tuvieran el valor de cadena vacía ('').

Ejemplo:

*Entrada:*

```xml
<xml>
  <foo bar="" />
</xml>
```

*Salida:*

```json
{
  "xml": {
    "foo": {
      "@bar": ""
    }
  }
}
```

4\. Los nodos hijos múltiples con el mismo nombre de elemento se convertirán en una sola clave que tiene como valor un array de valores.

Ejemplo:

*Entrada:*

```xml
<xml>
  <foo>BAR</foo>
  <foo>BAZ</foo>
  <foo>QUX</foo>
</xml>
```

*Salida:*

```json
{
  "xml": {
    "foo": ["BAR", "BAZ", "QUX"]
  }
}
```

5\. Si un elemento de texto no tiene atributos ni hijos, se convertirá como una cadena.

Ejemplo:

*Entrada:*

```xml
<xml>
    <foo>BAZ</foo>
</xml>
```

*Salida:*

```json
{
  "xml": {
    "foo": "BAZ"
   }
}
```

6\. Si un elemento de texto no tiene hijos pero sí atributos, el contenido de texto se convertirá en un elemento con la clave '\#text' y el contenido como valor; los atributos se convertirán como se describe en la regla de serialización 1.

Ejemplo:

*Entrada:*

```xml
<xml>
  <foo bar="BAR">
    BAZ
  </foo>
</xml>
```

*Salida:*

```json
{
  "xml": {
    "foo": {
      "@bar": "BAR",
      "#text": "BAZ"
    }
  }
}
```

[comment]: # ({/46c5de71-a12fbdc2})

[comment]: # ({89b707d3-1368a2b0})
### Funciones globales de JavaScript

Se han implementado funciones globales adicionales de JavaScript con Duktape:

-   `btoa(data)` - codifica los datos en una cadena base64.
-   `atob(base64_string)` - decodifica la cadena base64 como un buffer Uint8Array.

```javascript
try {
    b64 = btoa("test string");
    buffer = atob(b64);

    // Tenga en cuenta que la lógica de decodificación depende del formato de datos del buffer.
    decoded = String.fromCharCode.apply(this, [].slice.call(buffer));
} 
catch (error) {
    return {'error.name' : error.name, 'error.message' : error.message};
}
```

-   `md5(data)` - calcula el hash MD5 de los datos.
-   `sha256(data)` - calcula el hash SHA256 de los datos.
-   `hmac('<hash type>',key,data)` - devuelve un hash HMAC como una cadena en formato hexadecimal; se admiten `md5` y `sha256` como `hash type`; los parámetros `key` y `data` admiten datos binarios.

    Ejemplos:
    -    `hmac('md5',key,data)`
    -    `hmac('sha256',key,data)`
-   `sign(hash,key,data)` - devuelve la firma calculada (firma RSA con SHA-256) como una cadena, donde:<br>
    **hash** - solo se permite `sha256`, de lo contrario se lanza un error.<br>
    **key** - la clave privada.
    Debe corresponder al estándar PKCS#1 o PKCS#8.
    La clave puede proporcionarse en diferentes formas:<br>
    -    con espacios en lugar de saltos de línea
    -    con `\n` escapados o no escapados en lugar de saltos de línea
    -    sin ningún salto de línea como una cadena de una sola línea
    -    como una cadena en formato JSON

    La clave también puede cargarse desde una macro de usuario/macro secreta/vault.

    **data** - los datos que se firmarán.
    Puede ser una cadena (también se admiten datos binarios) o un buffer (Uint8Array/ArrayBuffer).

    Ejemplo:
    -    `sign('sha256',key,data)`

    Se utiliza OpenSSL o GnuTLS para calcular las firmas.
    Si Zabbix se compiló sin ninguna de estas bibliotecas de cifrado, se lanzará un error ('missing OpenSSL or GnuTLS library').

[comment]: # ({/89b707d3-1368a2b0})
