# Fragmentos de código

> Copia fragmentos de JavaScript listos para usar con Proxyman Scripting: edita encabezados, parámetros de consulta, cuerpos JSON y códigos de estado, mapea archivos locales, llama a APIs y mucho más.

## 1. ¿Qué es? {#1-whats-it}

Una colección de fragmentos de JavaScript para la herramienta Proxyman Scripting.

> **Nota:** ¿No encuentras el fragmento de código que buscas?
>
> Abre un ticket en [GitHub](https://github.com/ProxymanApp/Proxyman) y te ayudaremos ⭐️

> **Consejo:** Usa [Proxyman MCP](https://proxyman.com/docs/es/mcp) con tu agente (Codex/Claude Code) para generar scripts fácilmente 🚀

## 2. Habituales en solicitudes y respuestas {#2-common-on-request-and-response}

* [Actualizar encabezados de la solicitud o la respuesta](https://proxyman.com/docs/es/scripting/snippet-code#http-header)
* [Actualizar los parámetros de consulta de la solicitud](https://proxyman.com/docs/es/scripting/snippet-code#request-query)
* [Actualizar el cuerpo de formulario URLEncoded de la solicitud](https://proxyman.com/docs/es/scripting/snippet-code#urlencoded-form-body)
* [Actualizar el cuerpo JSON de la solicitud o la respuesta](https://proxyman.com/docs/es/scripting/snippet-code#json-body)
* [Mapear un archivo local al cuerpo de la respuesta como la herramienta Map Local](https://proxyman.com/docs/es/scripting/snippet-code#map-a-local-file-to-responses-body-like-map-local-tool-proxyman-2250)
* [Cambiar el esquema, host, puerto y ruta de la solicitud](https://proxyman.com/docs/es/scripting/snippet-code#change-request-destination-scheme-host-port-path)
* [Ajustes de ALPN y HTTP/2 upstream](https://proxyman.com/docs/es/scripting/snippet-code#upstream-alpn-and-http2-settings)
* [De HTTP a HTTPS](https://proxyman.com/docs/es/scripting/snippet-code#http-to-https)
* [De HTTPS a HTTP](https://proxyman.com/docs/es/scripting/snippet-code#https-to-http)
* [Cambiar el método de la solicitud](https://proxyman.com/docs/es/scripting/snippet-code#change-http-request-method)
* [Cambiar el código de estado de la respuesta](https://proxyman.com/docs/es/scripting/snippet-code#change-response-http-status-code)
* [Registro](https://proxyman.com/docs/es/scripting/snippet-code#logging)
* [Usar un archivo JSON como cuerpo de la solicitud o la respuesta](https://proxyman.com/docs/es/scripting/snippet-code#use-json-file-as-a-body-of-request-or-response)
* [Usar varios archivos JSON](https://proxyman.com/docs/es/scripting/snippet-code#use-multiple-json-files)
* [Map Local para GraphQL](https://proxyman.com/docs/es/scripting/snippet-code#map-local-with-graphql)
* [Usar ArrayBuffer en el cuerpo de la solicitud o la respuesta](https://proxyman.com/docs/es/scripting/snippet-code#use-arraybuffer-in-requestresponse-body)
* [Conservar el host](https://proxyman.com/docs/es/scripting/snippet-code#preserve-the-host)
* [Comment y Highlight con color](https://proxyman.com/docs/es/scripting/snippet-code#comment--highlight-with-color)
* [Abortar (cerrar) la conexión de la solicitud o la respuesta (como la herramienta Block List)](https://proxyman.com/docs/es/scripting/snippet-code#abort-the-requestresponse-like-block-list-tool)

### Multipart/form-data {#multipartform-data}

* [Leer, añadir, actualizar o eliminar una parte de multipart/form-data](https://proxyman.com/docs/es/scripting/snippet-code#multipartform-data-1)

## 3. Addons {#3-addons}

* [Codificación/decodificación Base64 o atob/btoa](https://proxyman.com/docs/es/scripting/snippet-code#use-base64-addon)
* [Addon de hash (MD5, SHA1, SHA256, SHA512)](https://proxyman.com/docs/es/scripting/snippet-code#use-hashing-addon-md5-sha1-sha256-sha512)
* [Generador UUIDv4](https://proxyman.com/docs/es/scripting/snippet-code#use-uuid-v4-addon)
* [Deflate/Inflate o GZip/UnGZip](https://proxyman.com/docs/es/scripting/snippet-code#deflateinflate-and-gzipungzip)
* [Decodificar JWT](https://proxyman.com/docs/es/scripting/snippet-code#jwt-decode)

## 3.1 Usar \`npm install\` {#31-use-npm-install}

* [Usar \`npm install dayjs\` para instalar paquetes npm de terceros](https://proxyman.com/docs/es/scripting/snippet-code#use-npm-install)

## 4. Expresiones regulares {#4-regex}

* [Comprobar si una cadena contiene solo números](https://proxyman.com/docs/es/scripting/snippet-code#regex)
* [Expresión regular para obtener el esquema, host, puerto, ruta y query de la URL](https://proxyman.com/docs/es/scripting/snippet-code#regex-to-get-the-scheme-host-port-path-and-query-of-the-url)

## 5. Importar y exportar archivos {#5-import--export-files}

* [Importar archivo JSON](https://proxyman.com/docs/es/scripting/snippet-code#json)
* [Importar datos binarios (imagen)](https://proxyman.com/docs/es/scripting/snippet-code#binary-file)
* [Importar archivos de texto (css, html, js....)](https://proxyman.com/docs/es/scripting/snippet-code#text-based-file)
* [Importar archivos sin usar la "Import Tool"](https://proxyman.com/docs/es/scripting/snippet-code#import-file-without-using-the-import-tool)
* [Escribir/exportar a un archivo local](https://proxyman.com/docs/es/scripting/snippet-code#write--export-to-a-local-file)
* [Comprobar si un archivo existe](https://proxyman.com/docs/es/scripting/snippet-code#check-if-the-file-exists)
* [Leer un archivo local](https://proxyman.com/docs/es/scripting/snippet-code#read-a-file)
* [Usar la respuesta como API simulada (mock)](https://proxyman.com/docs/es/scripting/snippet-code#use-as-mock-api)

## 6. Varios {#6-miscellaneous}

* [Evitar CORS](https://proxyman.com/docs/es/scripting/snippet-code#by-pass-cors)
* [Inyectar un encabezado en la solicitud o la respuesta](https://proxyman.com/docs/es/scripting/snippet-code#inject-header-to-request--response)
* [Retrasar la respuesta con la función sleep()](https://proxyman.com/docs/es/scripting/snippet-code#response-delay-with-sleep-function)

## 7. Cifrado/descifrado {#7-encryptiondecryption}

* [AES](https://proxyman.com/docs/es/scripting/snippet-code#aes-encryptiondecryption)
* [DES](https://proxyman.com/docs/es/scripting/snippet-code#des-encryptiondecryption)

## 8. Map Remote con Scripting {#8-map-remote-with-scripting}

* [Mapear endpoints de v1 a v2](https://proxyman.com/docs/es/scripting/snippet-code#map-v1-to-v2-endpoints)
* [Mapear localhost a producción](https://proxyman.com/docs/es/scripting/snippet-code#map-localhost-to-production)
* [Mapear producción a localhost](https://proxyman.com/docs/es/scripting/snippet-code#map-production-to-localhost)

## 9. Hacer solicitudes HTTP async/await (macOS) {#9-make-asyncawait-http-request-macos}

* [Solicitud GET con parámetros de consulta](https://proxyman.com/docs/es/scripting/snippet-code#get-request-with-query)
* [Solicitud POST con cuerpo JSON](https://proxyman.com/docs/es/scripting/snippet-code#post-request-with-json-body)
* [Solicitud POST con application/x-www-form-urlencoded](https://proxyman.com/docs/es/scripting/snippet-code#post-request-with-applicationx-www-form-urlencoded-body)
* [Solicitudes PUT / PATCH / DELETE](https://proxyman.com/docs/es/scripting/snippet-code#put--patch--delete-request)

## 9.1. Hacer solicitudes HTTP async/await (Windows/Linux) {#91-make-asyncawait-http-request-windowslinux}

* [Hacer una solicitud con la biblioteca Axios](https://proxyman.com/docs/es/scripting/snippet-code#make-asyncawait-http-request-windowslinux)

## 10. URL y URLSearchParams {#10-url-and-urlsearchparams}

* [URL y URLSearchParams](https://proxyman.com/docs/es/scripting/snippet-code#url-and-urlsearchparams)

## 11. Acceder a las variables de entorno {#11-access-environment-variables}

* [Leer manualmente las variables de entorno del sistema](https://proxyman.com/docs/es/scripting/snippet-code#reload-system-environment-variables)

## 12. WebSocket {#12-websocket}

* [Cambiar la URL de WebSocket y los encabezados](https://proxyman.com/docs/es/scripting/snippet-code#change-websocket-url-requestsresponse-header)
* [Registrar mensajes de WebSocket con onWebsocket](https://proxyman.com/docs/es/scripting/snippet-code#log-websocket-messages-with-onwebsocket)
* [Leer mensajes de texto y JSON](https://proxyman.com/docs/es/scripting/snippet-code#read-text-and-json-messages)
* [Inspeccionar mensajes binarios](https://proxyman.com/docs/es/scripting/snippet-code#inspect-binary-messages)
* [Registrar tramas ping y pong](https://proxyman.com/docs/es/scripting/snippet-code#log-ping-and-pong-frames)
* [Inspeccionar tramas de cierre](https://proxyman.com/docs/es/scripting/snippet-code#inspect-close-frames)
* [Modificar mensajes de WebSocket con onWebsocket](https://proxyman.com/docs/es/scripting/snippet-code#modify-websocket-messages-with-onwebsocket)
* [Cambiar un campo de los mensajes JSON](https://proxyman.com/docs/es/scripting/snippet-code#change-a-field-of-json-messages)
* [Reemplazar texto en ambas direcciones](https://proxyman.com/docs/es/scripting/snippet-code#replace-text-in-both-directions)
* [Descartar mensajes](https://proxyman.com/docs/es/scripting/snippet-code#drop-messages)
* [Responder a un mensaje del cliente sin el servidor](https://proxyman.com/docs/es/scripting/snippet-code#reply-to-a-client-message-without-the-server)
* [Enviar un mensaje al servidor](https://proxyman.com/docs/es/scripting/snippet-code#send-a-message-to-the-server)
* [Simular una conexión perdida](https://proxyman.com/docs/es/scripting/snippet-code#simulate-a-lost-connection)
* [Cambiar un mensaje binario](https://proxyman.com/docs/es/scripting/snippet-code#change-a-binary-message)

## Encabezado HTTP {#http-header}

### Añadir/actualizar: encabezado de la solicitud o la respuesta {#addupdate-request-or-response-header}

```javascript
function onRequest(context, url, request) {
    // Add or update Request Header
    request.headers["X-Proxyman-Key"] = "My-Value";
    request.headers.name = "Proxyman";
    return request;
}

function onResponse(context, url, request, response) {
    // Add or update Response Header
    response.headers["X-Proxyman-Key"] = "My-Value";
    response.headers.id = 100;
    return response;
}
```

### Eliminar: encabezado de la solicitud o la respuesta {#delete-request-or-response-header}

```javascript
function onRequest(context, url, request) {
    delete request.headers["X-Proxyman-Key"];
    return request;
}

function onResponse(context, url, request, response) {
    delete response.headers["X-Proxyman-Key"];
    return response;
}

```

## Parámetros de consulta de la solicitud {#request-query}

### Añadir/actualizar {#addupdate}

```javascript
function onRequest(context, url, request) {
    request.queries["name"] = "Proxyman";
    request.queries["platform"] = "macOS";
    // => http://proxyman.io?name=Proxyman&platform=macOS
    return request;
}
```

### Eliminar {#delete}

```javascript
function onRequest(context, url, request) {
    delete request.queries["name"];
    delete request.queries["platform"];
    return request;
}

```

## Cuerpo de formulario URLEncoded {#urlencoded-form-body}

### Añadir/actualizar {#addupdate-1}

```javascript
function onRequest(context, url, request) {
    // Make sure the Request Header is application/x-www-form-urlencoded
    // Content-Type: application/x-www-form-urlencoded   
    var formBody = request.body;

    formBody["name"] = "Proxyman";
    formBody["platform"] = "macOS";

    request.body = formBody; // => name=Proxyman&platform=macOS
    return request;
}

```

### Eliminar {#delete-1}

```javascript
function onRequest(context, url, request) {
    // Content-Type: application/x-www-form-urlencoded
    var formBody = request.body;

    delete formBody["name"];
    delete formBody["platform"];

    request.body = formBody;
    return request;
}

```

## Cambiar el destino de la solicitud (esquema, host, puerto, ruta) {#change-request-destination-scheme-host-port-path}

```javascript
function onRequest(context, url, request) {
    request.scheme = "http";
    request.host = "proxyman.dev";
    request.port = 9090;
    request.path = "v1/data/user";
    return request;
}
```

## Ajustes de ALPN y HTTP/2 upstream {#upstream-alpn-and-http2-settings}

Disponible en Proxyman v26.0.0 o posterior para macOS. Consulta [HTTP/2](https://proxyman.com/docs/es/basic-features/http2) para la configuración.

Define `request.upstream` en `onRequest` para cambiar la forma en que Proxyman se conecta al servidor. Activa "Enable SSL Proxying" para el dominio HTTPS. Las anulaciones de H2 también requieren que HTTP/2 esté activado en Settings y que el cliente se conecte a Proxyman mediante HTTP/2.

```javascript
async function onRequest(context, url, request) {
  request.upstream = {
    tls: { alpnProtocols: ["h2"] },
    http2: {
      headerTableSize: 65536,
      initialWindowSize: 6291456,
      maxHeaderListSize: 262144
    }
  };
  return request;
}
```

ALPN acepta una lista no vacía sin duplicados:

* `["h2"]`: Requiere HTTP/2. Falla si el servidor no puede usarlo.
* `["h2", "http/1.1"]`: Permite volver a HTTP/1.1.
* `["http/1.1"]`: Usa HTTP/1.1.

Los valores de HTTP/2 deben ser enteros desde `0` hasta el máximo indicado a continuación. Los campos omitidos o con `null` usan los valores predeterminados.

| Ajuste | Predeterminado | Máximo |
| --- | --- | --- |
| `headerTableSize` | `65536` | `4294967295` |
| `initialWindowSize` | `6291456` | `2147483647` |
| `maxHeaderListSize` | `262144` | `4294967295` |

Para restablecer todas las anulaciones, elimina `request.upstream` o asígnale `null`. Los ajustes no válidos o incompatibles devuelven un error local `502` de Scripting.

## De HTTP a HTTPS {#http-to-https}

```javascript
function onRequest(context, url, request) {
    request.scheme = "https";
    request.port = 443; // Don't forget to override the port
    return request;
}
```

## De HTTPS a HTTP {#https-to-http}

```javascript
function onRequest(context, url, request) {
    request.scheme = "http";
    request.port = 80; // Don't forget to override the port
    return request;
}
```

## Cambiar el método de la solicitud HTTP {#change-http-request-method}

```javascript
function onRequest(context, url, request) {
    request.method = "POST";
    return request;
}
```

## Cambiar el código de estado HTTP de la respuesta {#change-response-http-status-code}

```javascript
function onResponse(context, url, request, response) {
    response.statusCode = 404;
    return response;
}
```

## Cuerpo JSON {#json-body}

### En la solicitud {#on-request}

```javascript
function onRequest(context, url, request) {
    // Set JSON content
    request.headers["Content-Type"] = "application/json";
    
    // Get Request body
    var jsonBody = request.body;
    
    // Modify data
    jsonBody["name"] = "Proxyman";
    jsonBody["platform"] = "macOS";
    jsonBody["info"] = { 
                        "website": "proxyman.io",
                        "region": "Earth"
                       };
    // Set it again        
    request.body = jsonBody;
    return request;
}
```

### En la respuesta {#on-response}

```javascript
function onResponse(context, url, request, response)  {
    // Set JSON content
    response.headers["Content-Type"] = "application/json";
  
    // Get Request body
    var jsonBody = response.body;
    
    // Modify data
    jsonBody["name"] = "Proxyman";
    jsonBody["platform"] = "macOS";
    jsonBody["info"] = { 
                        "website": "proxyman.io",
                        "region": "Earth"
                       };
    // Set it again        
    response.body = jsonBody;
    return response;
}

```

### Multipart/form-data {#multipartform-data-1}

Desde Proxyman macOS 6.6.0 o posterior, puedes leer, añadir y eliminar partes de un multipart/form-data

```javascript
function onRequest(context, url, request) {
  // Only run for multipart requests
  if (!request.multipart) {
    return request;
  }

  var parts = request.multipart;

  // 1) List parts (debug)
  console.log("Multipart parts:", parts);

  // 2) Modify a text part by name
  for (var i = 0; i < parts.length; i++) {
    if (parts[i].name === "text_field") {
      var p = parts[i];
      p.body = "Updated text from script";
      parts[i] = p;
    }
  }

  // 3) Modify a file part by name (binary body as [UInt8])
  for (var i = 0; i < parts.length; i++) {
    if (parts[i].name === "file_field") {
      var p = parts[i];
      p.body = [72, 101, 108, 108, 111]; // "Hello"
      p.fileName = "hello.txt";
      p.contentType = "text/plain";
      parts[i] = p;
    }
  }

  // 4) Add a new text part
  parts.push({
    name: "new_field",
    body: "Added by script"
  });

  // 5) Remove a part by name
  var filtered = [];
  for (var i = 0; i < parts.length; i++) {
    if (parts[i].name !== "remove_me") {
      filtered.push(parts[i]);
    }
  }

  // Apply updates
  request.multipart = filtered;

  return request;
}
```

### Mapear un archivo local al cuerpo de la respuesta como la herramienta Map Local (Proxyman 2.25.0+) {#map-a-local-file-to-responses-body-like-map-local-tool-proxyman-2250}

Es una forma práctica de definir un archivo local como cuerpo con la propiedad `bodyFilePath`.

```javascript
// For request
request.bodyFilePath = "~/Desktop/image.png";

// For response
response.bodyFilePath = "~/Desktop/image.png";
```

```javascript
function onResponse(context, url, request, response) {
 
  response.headers["Content-Type"] = "image/png";
  response.bodyFilePath = "~/Desktop/image.png";
 
  // Done
  return response;
}
```

```javascript
function onResponse(context, url, request, response) {
 
  response.headers["Content-Type"] = "application/json";
  response.bodyFilePath = "~/Desktop/my_response.json";
 
  // Done
  return response;
}
```

### Usar un archivo JSON como cuerpo de la solicitud o la respuesta {#use-json-file-as-a-body-of-request-or-response}

Puedes usar un archivo JSON como cuerpo de la solicitud o de la respuesta.

Sigue los pasos de [Importar un archivo JSON](https://proxyman.com/docs/es/scripting/snippet-code#json).

### Usar varios archivos JSON {#use-multiple-json-files}

Puedes definir un cuerpo distinto para cada endpoint con una sentencia if.

1. Sigue los pasos de [Importar un archivo JSON](https://proxyman.com/docs/es/scripting/snippet-code#json) para importar un archivo JSON al script
2. Configura la Script Rule con un patrón comodín o una expresión regular que coincida con muchos endpoints. Por ejemplo, https://my-domain.com/v\*
3. Usa \`includes()\` para comprobar si el endpoint coincide

```javascript
const file_1 = require("@users/myfile_1.json");
const file_2 = require("@users/myfile_2.json");
const file_3 = require("@users/myfile_3.json");

function onResponse(context, url, request, response) {
  
  // Set JSON content
  response.headers["Content-Type"] = "application/json";
  
  // Check
  if (url.includes("v1/data")) {
    response.body = file_1
  } else if (url.includes("v2/login")) {
      response.body = file_2
  } else if (url.includes("v3/user")) {
      response.body = file_3
  }

  // Done
  return response;
}
```

### Map Local con GraphQL {#map-local-with-graphql}

Más información en [https://github.com/ProxymanApp/Proxyman/issues/412#issuecomment-697101594](https://github.com/ProxymanApp/Proxyman/issues/412#issuecomment-697101594)

```javascript
// Import your JSON file here 
const file = require("@users/B02D96D5.default_message_32E64A5B.json");

function onRequest(context, url, request) {

  // 1. Extract the queryName from the request
  var queryName = request.body.query.match(/\S+/gi)[1].split('(').shift();

  // 2. Save to sharedState
  sharedState.queryName = queryName

  // Done
  return request;
}

function onResponse(context, url, request, response) {

  // 3. Check if it's the request we need to map
  if (sharedState.queryName == "user") {
    
    // 4. Import the local file by Action Button -> Import
    // Get the local JSON file and set it as a body (like Map Local)
    response.headers["Content-Type"] = "application/json";
    response.body = file;
  }

  // Done
  return response;
}
```

### Usar ArrayBuffer en el cuerpo de la solicitud o la respuesta {#use-arraybuffer-in-requestresponse-body}

Como JavaScript no tiene el tipo de objeto Data, el cuerpo de tipo Data se convierte en una **cadena codificada en Base64** dentro de JavaScript. Para pasar un **Uint8Array**, un **blob** o un **ArrayBuffer** al cuerpo, asegúrate de convertirlo en una **cadena codificada en Base64** y de definir el Content-Type como `application/octet-stream`

Proxyman convertirá la codificación Base64 a ArrayBuffer, de modo que el cliente reciba los datos correctamente.

```javascript
// Import
const { btoa } = require('@addons/Base64.js');

function onResponse(context, url, request, response) {
  // Construct the ArrayBuffer
  const buffer = new ArrayBuffer(256)
  const view = new Uint8Array(buffer)
  for (let i = 0; i < view.length; i++) {
    view[i] = i
  }
  
  // Convert ArrayBuffer to Base64String
  var newBody = btoa(String.fromCharCode.apply(null, new Uint8Array(buffer)));
  
  // Set new body
  response.body = newBody;
  response.statusCode = 200
  response.headers['Content-Type'] = 'application/octet-stream'

  // Done
  return response;
}
```

### Conservar el host {#preserve-the-host}

```javascript
function onRequest(context, url, request) {
    request.preserveHostHeader = true
    return request
}
```

### Comment y Highlight con color {#comment--highlight-with-color}

Usa `comment` o `color` para resaltar el flujo en la vista principal de la tabla.

```javascript
function onRequest(context, url, request) {
    request.comment = "It's a Request"
    request.color = "red" // red, blue, yellow, purple, gray, green
    return request
}

function onResponse(context, url, request, response) {
    response.comment = "It's a Response"
    response.color = "yellow" // red, blue, yellow, purple, gray, green
    return response
}
```

![Lista de solicitudes de Proxyman con filas resaltadas, una fila tachada y notas en la columna Comment](https://proxyman.com/docs/assets/proxyman-highlight-color-comment.jpg)

_Filas con colores y comentarios_

## Importar archivos con require() {#import-files-with-require}

### JSON {#json}

1. Prepara un archivo JSON y guárdalo en tu escritorio

```javascript
// myfile.json
{
  "name": "Proxyman",
  "platform": "macOS",
  "info": {
    "website": "proxyman.io",
    "region": "Earth"
  }
}
```

2\. Haz clic en **More** -> **Import JSON or Other File...** y selecciona tu archivo

![Menú More del editor de scripts de Proxyman con Import JSON or Other File resaltado](https://proxyman.com/docs/assets/Screen%20Shot%202021-04-22%20at%2010.59.46.png)

3\. Proxyman añadirá el código de importación al principio del script

```javascript
// ~/Library/Application Support/com.proxyman.NSProxy/users/myfile.json
const file = require("@users/myfile.json");

function onResponse(context, url, request, response) {
  // 1. Set header to JSON if need
  response.headers["Content-Type"] = "application/json";

  // 2. Set Body as a imported file
  response.body = file;
  
  return response;
}
```

> **Nota:** El archivo seleccionado se copia en la carpeta **\~/Library/Application\ Support/com.proxyman.NSProxy/users**.

> **Nota:** Para otros tipos de archivo, como imágenes, texto o PDF, asegúrate de definir el **encabezado Content-Type** correcto.

### Archivo binario {#binary-file}

1. Sigue las mismas instrucciones de arriba (selecciona tu archivo binario)
2. Asígnalo como cuerpo

```javascript
// ~/Library/Application Support/com.proxyman.NSProxy/users/myscreenshot.png
const file = require("@users/myscreenshot.png");

function onResponse(context, url, request, response) {
  // Set header
  response.headers["Content-Type"] = "image/png";

  // Set Body
  response.body = file;
  
  return response;
}
```

### Archivo de texto {#text-based-file}

1. Sigue las mismas instrucciones de arriba (selecciona tu archivo de texto)
2. Asígnalo como cuerpo

```javascript
// ~/Library/Application Support/com.proxyman.NSProxy/users/main.css
const file = require("@users/main.css");

function onResponse(context, url, request, response) {
  // Set header
  response.headers["Content-Type"] = "text/css";

  // Set Body
  response.body = file;
  
  return response;
}
```

### Importar archivos sin usar la "Import Tool" {#import-file-without-using-the-import-tool}

A partir de Proxyman 2.24.0 o posterior, puedes importar cualquier archivo sin usar la "Import Tool".

```javascript
// Import your file from your Desktop folder
const file = require("~/Desktop/myfile.json");

function onResponse(context, url, request, response) {

  // 1. Set header to JSON if need
  response.headers["Content-Type"] = "application/json";

  // 2. Set Body as a imported file
  response.body = file;
  
  return response;
}
```

* Si el archivo tiene la extensión ".js" => Proxyman lo ejecutará como un script de JS
* En caso contrario, Proxyman lo importará como un archivo normal

> **Nota:** Solo se incluyen los archivos importados con la "Import Tool" cuando exportas el script a un colega.

### Usar como API simulada (mock) {#use-as-mock-api}

Puedes usar Scripting como API simulada (mock). Consulta [Usar Scripting como API simulada (mock)](https://proxyman.com/docs/es/scripting/script#8-use-scripting-as-a-mock-api).

## Usar addons {#using-addons}

[Lista completa de addons integrados](https://proxyman.com/docs/es/scripting/addons)

### Usar el addon Base64 {#use-base64-addon}

```javascript
// Encode Base64
const { btoa } = require("@addons/Base64.js")

// Usage:
var text = "HelloWorld";
var encodedText = btoa(text);
```

```javascript
// Decode Base64
const { atob } = require("@addons/Base64.js")

// Usage:
var text = atob("aGVsbG8=");
```

### Usar el addon de hash (MD5, SHA1, SHA256, SHA512) {#use-hashing-addon-md5-sha1-sha256-sha512}

```javascript
// Hash MD5
const { md5 } = require("@addons/MD5.js")

// Usage:
var hashedText = md5("Hello World");
```

```javascript
// Hash SHA1
const { sha1 } = require("@addons/SHA1.js")

// Usage:
var hashedText = sha1("Hello World");
```

### Usar el addon UUID-v4 {#use-uuid-v4-addon}

```javascript
// Generate UUID v4
const { uuidv4 } = require("@addons/UUID.js")

// Usage:
var uuid = uuidv4();
```

## Deflate/Inflate y GZip/UnGZip {#deflateinflate-and-gzipungzip}

### Deflate/inflate {#deflateinflate}

```javascript
const { inflate, deflate } = require("@addons/Pako.js")

// Compress
var input = "Hello World from Pako!!!"
var result = deflate(input);
console.log(result); // eJzzSM3JyVcIzy/KSVFIK8rPVQhIzM5XVFQEAGsMB/8=

// Decompress
var text = 'eJzzSM3JyVcIzy/KSVFIK8rPVQhIzM5XVFQEAGsMB/8=';
var rawText = inflate(text);
console.log(rawText); // Hello World from Pako!!!
```

### GZip/UnGZip {#gzipungzip}

```javascript
const { ungzip, gzip } = require("@addons/Pako.js")

// Compress
var text =  'HelloWorld';
var result = gzip(text);
console.log(result); // H4sIAAAAAAAAA/NIzcnJD88vykkBAHkMd3cKAAAA

// Decompress
var text =  'H4sIAAAAAAAAA/NIzcnJD88vykkBAHkMd3cKAAAA';
var rawText = ungzip(text);
console.log(rawText); // HelloWorld
```

### Decodificar JWT {#jwt-decode}

```javascript
const { jwtDecode } = require('@addons/JWTDecode.js');

var text = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
var jSONObject = jwtDecode(text)
```

## Registro (logging) {#logging}

```javascript
// Print the obj
const myObj = {};
console.log(myObj);

// Print type of the obj
console.log(typeof(myObj));
```

## Expresiones regulares {#regex}

### Solo números {#only-number}

```javascript
//Init Regex
var reg = /^-?\d*\.?\d*$/;

if (reg.test("123123123")) {
    console.log("Matched");
}
```

### Expresión regular para obtener el esquema, host, puerto, ruta y query de la URL {#regex-to-get-the-scheme-host-port-path-and-query-of-the-url}

```javascript
function onRequest(context, url, request) {
  console.log(url);

  // Get each part
  const regex = /^(https?):\/\/([^:\/\n]+)(?::(\d+))?([^#\n?]+)(?:\?([^#\n]+))?/;
  const [, scheme, host, port, path, query] = url.match(regex);

  // Assign again
  request.scheme = scheme;
  request.host = host;
  if (port !== undefined) {
    request.port = parseInt(port);
  }
  request.path = path;

  // Log
  console.log("----------");
  console.log(scheme);
  console.log(host);
  console.log(port);
  console.log(path);

  // Done
  return request;
}
```

## Varios {#miscellaneous}

### Evitar CORS {#by-pass-cors}

```javascript
function onResponse(context, url, request, response) {  

  // Allow all
  response.headers["Access-Control-Allow-Origin"] = "*";
  response.headers["Access-Control-Allow-Headers"] = "*";
  response.headers["Access-Control-Allow-Methods"] = "*";

  // Done
  return response;
}
```

### Inyectar encabezados en la solicitud o la respuesta {#inject-header-to-request--response}

```javascript
function onRequest(context, url, request) {
  // add header
  request.headers["My-Injected-Header"] = "Proxyman";
  return request
}

function onResponse(context, url, request, response) {    
  // add header
  response.headers["My-Injected-Header"] = "Proxyman";
  return response;
}

```

### Retrasar la respuesta con la función sleep() {#response-delay-with-sleep-function}

Es útil para simular una red lenta ("Slow Network") en una solicitud o respuesta concreta. Para una herramienta con interfaz gráfica, consulta [Network Conditions](https://proxyman.com/docs/es/advanced-features/network-throttling#1-whats-it).

* macOS

```javascript
function onResponse(context, url, request, response) {
  console.log("Start sleep");
  
  // Sleep 5 seconds
  sleep(5000);
  
  // Done
  return response;
}
```

* Windows/Linux

```javascript
async function onResponse(context, url, request, response) {
  console.log("Start sleep");
  
  // Sleep 5 seconds
  // Must use `await` keyword on Windows/Linux
  await sleep(5000);
  
  // Done
  return response;
}
```

### Cifrado/descifrado AES {#aes-encryptiondecryption}

```javascript
const { encryptAES, decryptAES } = require("@addons/CryptoJS.js")

function onRequest(context, url, request) {
  
  // Encrypt
  var message = 'my message from Proxyman';
  var password = 'secret key 123';
  var ciphertext = encryptAES(message, password);
  
  // Decrypt
  var originalText = decryptAES(ciphertext, password);

  // Done
  return request;
}
```

### Cifrado/descifrado DES {#des-encryptiondecryption}

```javascript
const { encryptDES, decryptDES } = require("@addons/CryptoJS.js")

function onRequest(context, url, request) {
  
  // Encrypt
  var message = 'my message from Proxyman';
  var password = 'secret key 123';
  var ciphertext = encryptDES(message, password);
  
  // Decrypt
  var originalText = decryptDES(ciphertext, password);

  // Done
  return request;
}
```

### Escribir/exportar a un archivo local {#write--export-to-a-local-file}

* Override Mode

```javascript
function onResponse(context, url, request, response) {

  // Write to single file
  writeToFile(response.body, "~/Desktop/body.json");
  
  // Write the Body to file with flow ID
  writeToFile(response.body, "~/Desktop/sample-" + context.flow.id);
  
  // Done
  return response;
}
```

* Append Mode (solo para Proxyman 3.6.2+)

```javascript
async function onResponse(context, url, request, response) {

  // Append to the existed file
  // Or create a new file if it doesn't exist
  var opt = {appendFile: true}
  writeToFile(response.body, "~/Desktop/body.json", opt);

  // Done
  return response;
}
```

### Comprobar si el archivo existe {#check-if-the-file-exists}

* Disponible: Proxyman macOS 5.4.0+

```javascript
async function onRequest(context, url, request) {

  const filePath = "~/Desktop/myfile.json"
  
  // check if the file exists
  if (isFileExists(filePath)) {
    console.log("File exists");
  } else {
    console.log("File NOT exists");  
  }
  
  // Done
  return request;
}
```

### Leer un archivo {#read-a-file}

* Si es de texto -> devuelve un **String**
* En caso contrario -> devuelve un **Uint8Array**
* Disponible: Proxyman macOS 5.4.0+

```javascript
async function onRequest(context, url, request) {  // console.log(request);

  const textFilePath = "~/Desktop/myfile.json";
  
  // check exist
  if (isFileExists(textFilePath)) {
  
    // read from file
    const text = readFromFile(textFilePath);
    
    // parse string to JSON Object
    const obj = JSON.parse(text);
  }
  
  // Read binary file
  const binaryFilePath = "~/Desktop/screenshot.png";
  const binaryFile = readFromFile(binaryFilePath); // Uint8Array
  
  // Done
  return request;
}
```

## Map Remote {#map-remotes}

### Mapear endpoints de v1 a v2 {#map-v1-to-v2-endpoints}

```javascript
function onRequest(context, url, request) {
  
  // Replace v1 to v2 in URL Path
  var newPath = request.path.replace("v1", "v2");
  request.path = newPath

  // Done
  return request;
}
```

### Mapear localhost a producción {#map-localhost-to-production}

```javascript
function onRequest(context, url, request) {
  
  // Use production URL
  request.scheme = "https";
  request.host = "proxyman.io";
  request.port = 443;

  // Done
  return request;
}
```

### Mapear producción a localhost {#map-production-to-localhost}

```javascript
function onRequest(context, url, request) {
  
  // Use localhost URL
  request.scheme = "http";
  request.host = "localhost";
  request.port = 3000;

  // Done
  return request;
}
```

## Hacer solicitudes HTTP async/await (macOS) {#make-asyncawait-http-request-macos}

> **Nota:** \`$http\` está disponible en macOS. Para Windows/Linux, consulta la siguiente sección.

### Solicitud GET con parámetros de consulta {#get-request-with-query}

```javascript
async function onResponse(context, url, request, response) {  
  // GET Request with Query
  var url = "https://httpbin.proxyman.app/get?id=proxyman&country=united%20states";
  var output = await $http.get(url);
  
  // Get Status Code
  console.log(output.statusCode);
  
  // Get body
  console.log(output.body)
  
  // Get header
  console.log(output.headers)
  
  // Done
  return response;
}
```

### Solicitud POST con cuerpo JSON {#post-request-with-json-body}

```javascript
async function onResponse(context, url, request, response) {  
  // Define JSON Body and Header
  // Make sure "Content-Type" is "application/json"
  var param = {
    body: {
      "user": {
        "name": "Proxyman"
      }
    },
    headers: {
      "Content-Type": "application/json"
    }
  }

  // POST request with await
  var output = await $http.post("https://httpbin.proxyman.app/post", param);
  
  // Get Status Code
  console.log(output.statusCode);
  
  // Get body
  console.log(output.body)
  
  // Get header
  console.log(output.headers)
  
  // Done
  return response;
}
```

### Solicitud POST con cuerpo application/x-www-form-urlencoded {#post-request-with-applicationx-www-form-urlencoded-body}

```javascript
async function onResponse(context, url, request, response) {  
  // Define form Body and Header
  // Make sure "Content-Type" is "application/x-www-form-urlencoded"
  var param = {
    body: {
      "key1": "value1",
      "key2": "value2"
    },
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    }
  }

  // POST request with await
  var output = await $http.post("https://httpbin.proxyman.app/post", param);
  
  // Get Status Code
  console.log(output.statusCode);
  
  // Get body
  console.log(output.body)
  
  // Get header
  console.log(output.headers)
  
  // Done
  return response;
}
```

### Solicitudes PUT / PATCH / DELETE {#put--patch--delete-request}

```javascript
async function onRequest(context, url, request) {  

  var param = {
    body: {
      "user": {
        "name": "Proxyman"
      }
    },
    headers: {
      "Content-Type": "application/json"
    }
  }

  var output = await $http.post("https://httpbin.proxyman.app/post", param);
  var output = await $http.put("https://httpbin.proxyman.app/put", param);
  var output = await $http.delete("https://httpbin.proxyman.app/delete", param);
  
  // Done
  return request;
}
```

## Hacer solicitudes HTTP async/await (Windows/Linux) {#make-asyncawait-http-request-windowslinux}

Windows/Linux incluye la biblioteca [Axios](https://github.com/axios/axios) integrada. Puedes hacer solicitudes HTTP(s) fácilmente con la sintaxis de \`Axios\`.

```javascript
async function getUser() {
  try {
    const response = await axios.get('https://httpbin.proxyman.app/user?ID=12345');
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}
```

## Abortar la solicitud o la respuesta como la herramienta Block List {#abort-the-requestresponse-like-block-list-tool}

* Solo disponible en Proxyman 3.11.0 o posterior

### Abortar la solicitud {#abort-the-request}

```javascript
function onRequest(context, url, request) {
  // drop the connection
  abort();
}
```

```javascript
function onRequest(context, url, request) {

  // Use the if to abort on certain conditions
  if (true) {
    abort();
    return; // Must return a void to stop the func
  }

  // Done
  return request;
}
```

### Abortar la respuesta {#abort-the-response}

```javascript
function onResponse(context, url, request, response) {    
  // drop the connection
  abort();
}
```

## URL y URLSearchParams {#url-and-urlsearchparams}

A partir de Proxyman 4.13.0 o posterior, [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) y [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) son compatibles de forma nativa.

```javascript
function onRequest(context, url, request) {

  // URL
  const urlObj = new URL("https://proxyman.io/api/v1/user?id=123");
  console.log(urlObj.hostname);
  console.log(urlObj.search);
  console.log(urlObj.searchParams);

  // URLSearchParams
  const params1 = new URLSearchParams("foo=1&bar=2");
  
  // Done
  return request;
}
```

## Recargar las variables de entorno del sistema {#reload-system-environment-variables}

Proxyman macOS 4.15.0 o posterior.

Primero activa el permiso: botón **More** -> **Environment Variables** -> **Allow all scripts to access Environment Variables**.

```javascript
async function onRequest(context, url, request) {
  // manually reload to get the latest changes
  _reloadEnv();
  
  // get env
  console.log($PROXYMAN_ID)
  
  // Done
  return request;
}
```

## Cambiar la URL de WebSocket y los encabezados de solicitud/respuesta {#change-websocket-url-requestsresponse-header}

* Compatible desde Proxyman 6.2.0 o posterior para macOS.
* `onRequest` y `onResponse` modifican la URL y los encabezados del handshake. Para leer los mensajes, usa [onWebsocket](https://proxyman.com/docs/es/scripting/snippet-code#log-websocket-messages-with-onwebsocket) (Proxyman 26.1.0 o posterior para macOS, Windows y Linux). Para modificarlos, usa [Modify WebSocket Messages](https://proxyman.com/docs/es/scripting/snippet-code#modify-websocket-messages-with-onwebsocket) (Proxyman 26.2.0 o posterior para macOS, o Proxyman 26.1.0 o posterior para Windows/Linux).

**Mapear de localhost a producción**

* Rule ws://proxyman.debug:3000

```js
async function onRequest(context, url, request) {
  // console.log(request);
  console.log(url);

  request.scheme = "wss";
  request.host = "wss.httpbin-proxyman.xyz"
  request.port = 443

  // Done
  return request;
}

```

**De producción a localhost**

* Rule wss://echo.websocket.org

```js
async function onRequest(context, url, request) {
  // console.log(request);
  console.log(url);

  request.scheme = "ws";
  request.host = "proxyman.debug"
  request.port = 3000

  // Done
  return request;
}

```

## Registrar mensajes de WebSocket con onWebsocket {#log-websocket-messages-with-onwebsocket}

> **Aviso:** Estos fragmentos de `onWebsocket` requieren **Proxyman 26.1.0 o posterior para macOS, Windows y Linux**. No están disponibles en iOS.

Haz coincidir la URL `ws://` o `wss://` capturada, guarda y activa el script, y después vuelve a conectar el WebSocket. Consulta [Scripting with WebSocket](https://proxyman.com/docs/es/scripting/script#41-scripting-with-websocket) para la configuración y el objeto `message` completo.

Cada ejemplo define una función `onWebsocket` independiente. Usa un solo ejemplo o combina las comprobaciones en una única función. Sin la opción **Modify WebSocket Messages**, el hook es de solo lectura: cambiar `message` o devolver un valor no modifica el tráfico. Para cambiar mensajes, consulta [Modificar mensajes de WebSocket con onWebsocket](https://proxyman.com/docs/es/scripting/snippet-code#modify-websocket-messages-with-onwebsocket).

Registra cada mensaje capturado en ambos sentidos:

```javascript
function onWebsocket(context, url, request, response, message) {
  console.log(`[${message.from}] ${message.type}: ${message.data}`);
}
```

### Leer mensajes de texto y JSON {#read-text-and-json-messages}

Inspecciona el texto enviado por el servidor. Los mensajes JSON se analizan cuando son válidos; el resto del texto se registra sin cambios.

```javascript
function onWebsocket(context, url, request, response, message) {
  if (message.type !== "text" || message.from !== "server") return;

  try {
    const payload = JSON.parse(message.data);
    console.log("Server JSON: " + JSON.stringify(payload, null, 2));
  } catch (error) {
    // A text message does not have to contain JSON.
    console.log("Server text: " + message.data);
  }
}
```

Proxyman reensambla las tramas de texto fragmentadas antes de llamar al hook, así que aquí puedes analizar el mensaje JSON completo. Los fragmentos binarios también se reensamblan; no existe un callback independiente para las tramas de continuación.

### Inspeccionar mensajes binarios {#inspect-binary-messages}

Usa `message.rawData` para acceder a los bytes originales. `message.data` es solo una representación de texto y puede ser `Binary (length=N)`.

```javascript
function onWebsocket(context, url, request, response, message) {
  if (message.type !== "binary") return;

  const bytes = message.rawData;
  // Limit the preview so large messages do not flood the console.
  const hex = Array.from(bytes.slice(0, 32))
    .map(byte => byte.toString(16).padStart(2, "0"))
    .join(" ");
  const suffix = bytes.length > 32 ? " ..." : "";
  console.log(`[${message.from}] binary (${bytes.length} bytes): ${hex}${suffix}`);
}
```

`rawData` es un `Uint8Array` copiado y no es enumerable. Accede a él directamente; no esperes que `console.log(message)` o `JSON.stringify(message)` lo incluyan.

### Registrar tramas ping y pong {#log-ping-and-pong-frames}

Usa estos eventos para inspeccionar el tráfico de heartbeat en ambos sentidos. No se exponen los payloads de ping ni de pong.

```javascript
function onWebsocket(context, url, request, response, message) {
  if (message.type !== "ping" && message.type !== "pong") return;

  console.log(`[${message.from}] ${message.type} on ${url}`);
}
```

### Inspeccionar tramas de cierre {#inspect-close-frames}

Registra el código de cierre y el lado que envió la trama. No se expone el motivo del cierre.

```javascript
function onWebsocket(context, url, request, response, message) {
  if (message.type !== "close") return;

  console.log(`[${message.from}] closed with code ${message.closeCode}`);
}
```

## Modificar mensajes de WebSocket con onWebsocket {#modify-websocket-messages-with-onwebsocket}

> **Aviso:** Estos fragmentos requieren **macOS Proxyman 26.2.0 o posterior** o **Windows/Linux Proxyman 26.1.0 o posterior**. No están disponibles en iOS.

Marca **Modify WebSocket Messages** en la regla, deja **Request** marcado, guarda y activa el script, y después vuelve a conectar el WebSocket. Consulta [Modify WebSocket Messages](https://proxyman.com/docs/es/scripting/modify-websocket-messages) para la configuración y el efecto de cada valor de retorno:

* `return message`: envía el mensaje con tus cambios.
* `return null`: descarta el mensaje.
* No return: envía el mensaje original.
* `sendToClient(data)` / `sendToServer(data)`: envía un mensaje nuevo. Un String envía un mensaje de texto y un `Uint8Array` envía un mensaje binario.
* `abort()`: cierra el WebSocket en ambos lados.

### Cambiar un campo de los mensajes JSON {#change-a-field-of-json-messages}

Cambia un campo de cada mensaje JSON enviado por el servidor. Los demás mensajes se envían tal como están.

```javascript
function onWebsocket(context, url, request, response, message) {
  if (message.type !== "text" || message.from !== "server") {
    return message;
  }

  try {
    const json = JSON.parse(message.data);
    if (json.type === "price") {
      json.price = 0;
      message.data = JSON.stringify(json);
    }
  } catch (error) {
    // Not JSON: send it as it is
  }
  return message;
}
```

### Reemplazar texto en ambas direcciones {#replace-text-in-both-directions}

Cambia el nombre de host en todos los mensajes de texto, tanto del cliente como del servidor.

```javascript
const FIND_REGEX = /staging\.example\.com/g;
const REPLACE_WITH = "api.example.com";

function onWebsocket(context, url, request, response, message) {
  if (message.type === "text") {
    message.data = message.data.replace(FIND_REGEX, REPLACE_WITH);
  }
  return message;
}
```

### Descartar mensajes {#drop-messages}

Descarta los mensajes del cliente que coincidan con una expresión regular, por ejemplo los eventos de analítica. El servidor nunca los recibe.

```javascript
const DROP_REGEX = /"type"\s*:\s*"analytics"/;

function onWebsocket(context, url, request, response, message) {
  if (message.from === "client" && message.type === "text" && DROP_REGEX.test(message.data)) {
    console.log("Dropped: " + message.data);
    return null;
  }
  return message;
}
```

### Responder a un mensaje del cliente sin el servidor {#reply-to-a-client-message-without-the-server}

Responde a un mensaje del cliente con `sendToClient()` y descarta el original para que el servidor nunca lo reciba. Es útil para simular una respuesta del servidor.

```javascript
function onWebsocket(context, url, request, response, message) {
  if (message.from === "client" && message.type === "text" && message.data.includes('"subscribe"')) {
    sendToClient(JSON.stringify({ type: "error", code: 503, text: "Service unavailable" }));
    return null;
  }
  return message;
}
```

Los mensajes enviados con `sendToClient()` y `sendToServer()` no vuelven a ejecutar `onWebsocket()`, así que el script no puede entrar en un bucle infinito.

### Enviar un mensaje al servidor {#send-a-message-to-the-server}

Envía un mensaje adicional al servidor cuando el cliente envíe su primer mensaje, por ejemplo para suscribirse a otro canal.

```javascript
let isSubscribed = false;

function onWebsocket(context, url, request, response, message) {
  if (message.from === "client" && message.type === "text" && !isSubscribed) {
    isSubscribed = true;
    sendToServer(JSON.stringify({ type: "subscribe", channel: "ETH" }));
  }
  return message;
}
```

El código fuera de `onWebsocket()` se ejecuta una vez por conexión, así que `isSubscribed` empieza en `false` en cada conexión nueva.

### Simular una conexión perdida {#simulate-a-lost-connection}

Cierra el WebSocket en ambos lados después de 10 mensajes, para comprobar cómo se reconecta tu app.

```javascript
const CLOSE_AFTER_MESSAGES = 10;
let messageCount = 0;

function onWebsocket(context, url, request, response, message) {
  messageCount += 1;
  if (messageCount === CLOSE_AFTER_MESSAGES) {
    console.log("Closing the WebSocket after " + messageCount + " messages");
    abort();
  }
  return message;
}
```

### Cambiar un mensaje binario {#change-a-binary-message}

Define nuevos bytes con un `Uint8Array`. Un mensaje conserva su tipo: un mensaje binario sigue siendo binario.

```javascript
function onWebsocket(context, url, request, response, message) {
  if (message.type === "binary" && message.from === "server") {
    message.rawData = new Uint8Array([1, 2, 3]);
  }
  return message;
}
```

## Usar \`npm install\` {#use-npm-install}

Lee más en [use-npm-install.md](https://proxyman.com/docs/es/scripting/use-npm-install)

### Instalar un paquete {#install-a-package}

Abre Terminal e instala paquetes en la carpeta Application Support de Proxyman:

* Instala `dayjs`

```bash
$ cd "$HOME/Library/Application Support/com.proxyman.NSProxy"
$ npm install --prefix . dayjs --ignore-scripts --no-audit --no-fund
```

Después de la instalación, el paquete debería existir en:

```
~/Library/Application Support/com.proxyman.NSProxy/node_modules
```

### Usar un paquete en un script {#use-a-package-in-a-script}

Usa el nombre del paquete con `require()`:

```javascript
const dayjs = require("dayjs");

async function onRequest(context, url, request) {
  const formattedDate = dayjs("2026-05-05T13:00:00Z").format("YYYY-MM-DD");
  request.headers["X-Proxyman-Dayjs"] = formattedDate;
  return request;
}
```
