- Primeros pasos
- Mejores prácticas
- Tenant
- Acerca del contexto de tenant
- Buscar recursos en un tenant
- Gestionar robots
- Conexión de los robots a Orchestrator
- Almacenar credenciales de robots en CyberArk
- Almacenar contraseñas de robots desatendidos en Azure Key Vault (solo lectura)
- Almacenar las credenciales de robots desatendidos en HashiCorp Vault (solo lectura)
- Almacenamiento de credenciales de Unattended Robot en AWS Secrets Manager (solo lectura)
- Eliminar sesiones desconectadas y sin respuesta no atendidas
- Autenticación de Robot
- Autenticación de robots con credenciales de cliente
- Configurar las capacidades de automatización
- Auditoría
- Configuración
- Cloud Robots
- Contexto de carpetas
- Automatizaciones
- Procesos
- Trabajos
- Apps
- Desencadenadores
- Desencadenadores de tiempo
- Desencadenadores de colas
- Desencadenadores de eventos
- Explicación de los modos de llamada
- Administrar días no laborables
- Registros
- Supervisión
- Colas
- Activos
- Depósitos de almacenamiento
- Test Suite - Orchestrator
- Servicio de catálogo de recursos
- Integraciones
- Solución de problemas
Explicación de los modos de llamada
Los modos de llamada de los desencadenadores de la API están diseñados específicamente para crear y seguir ejecuciones de trabajos en Orchestrator.
El reto fundamental de la comunicación basada en HTTP es que es intrínsecamente sincrónica: normalmente, el cliente envía una solicitud y espera la respuesta del servidor. Sin embargo, en el contexto de los trabajos de UiPath Robot, Orchestrator no permite mantener la conexión abierta hasta que el trabajo haya finalizado.
Con el fin de evitarlo, hemos utilizado el protocolo HTTP para modelar varios modos de llamada. Estos modos se basan en métodos, códigos de estado y encabezados HTTP estándar para crear, supervisar y obtener el resultado de los trabajos dentro del sistema, sin mantener la conexión abierta innecesariamente. Cada uno de los modos de llamada propuestos tiene ventajas e inconvenientes, así que puedes elegir el que mejor se adapte a tus necesidades de integración. Ten en cuenta que, para garantizar una comunicación segura, cada llamada requiere la autenticación adecuada mediante tokens al portador.
Problema conocido
502 Bad Gateway
, causado por mantener un gran número de conexiones activas durante intervalos de tiempo prolongados. El trabajo subyacente de tal solicitud puede haberse ejecutado a pesar del error, por lo que puedes comprobar su estado en Orchestrator.
Este problema es intermitente y cualquier solicitud posterior funcionará como se espera.
Este modo de llamada implica realizar una llamada con el verbo HTTP preconfigurado para desencadenar un nuevo trabajo y recibir un URI de estado. El URI de estado debe sondearse manualmente hasta que se complete el trabajo. En este punto, la llamada se redirige a otro punto final, que se utiliza para recuperar el resultado del trabajo (salida o error).
Flujo de trabajo de sondeo asíncrono en el que la finalización del trabajo depende de llamadas manuales intermedias a la ubicación de respuesta.
La llamada inicial se realiza utilizando el verbo HTTP configurado (OBTENER, PUBLICAR, PONER, ELIMINAR), que crea el trabajo asociado en Orchestrator. Una vez creado el trabajo, el sistema responde con un código de estado HTTP 202 (Aceptado) y un URI de estado en el encabezado Ubicación.
Una vez creado el trabajo, deberás comprobar periódicamente su estado. Durante este proceso de sondeo, mientras el trabajo esté en ejecución, cada petición OBTENER al URI de estado devuelve un código de estado HTTP 200 (OK). Cuando se completa el trabajo, la siguiente solicitud OBTENER al URI de estado devuelve un código de estado HTTP 303 (ver Otros), redirigiendo al URI de salida (a través del encabezado Ubicación). Se espera que siga el URI de salida para recuperar el resultado del trabajo (salida o error).
Asegúrate siempre de incluir un token al portador válido en el encabezado de cada llamada para que la autenticación se realice correctamente.
Este ejemplo ilustra cómo iniciar un trabajo a través de un desencadenador de API desde un explorador, utilizando el modo de llamada de sondeo asíncrono.
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
const body = {
'argument1': 123,
'argument2': 'my string',
'$callMode': 'AsyncRequestReply' // optional argument to force call mode to AsyncRequestReply
}
// if invocation is done by GET, place the parameters in query string and remove the 'Content-Type' header
const invokeRequestOptions = {
method: 'POST',
headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
body: JSON.stringify(body),
};
const redirectRequestOptions = {
method: "GET",
credentials: 'same-origin',
headers: new Headers({ Authorization: `Bearer ${token}` }),
redirect: "follow", // this option must be set to follow, otherwise an 'opaqueredirect' response is returned
};
const response = await fetch(url, invokeRequestOptions);
let newLocation = response.headers.get("Location");
// first response should be 202 and have a location header
console.log(`Got ${response.status}, with location: ${newLocation}`);
for (let i = 0; i < 20; i++) {
await sleep(SLEEP_DURATION);
// follow the location header to the new endpoint
const statusResponse = await fetch(newLocation, redirectRequestOptions);
// if the response was redirected (and automatically followed), then the output endpoint has been reached
// the output of the job can be found in the body of the response in JSON format
if (statusResponse.status != 200 || statusResponse.redirected)
{
// read the job output
const output = await statusResponse.json();
console.log(`Got ${statusResponse.status}, with body: ${JSON.stringify(output)}`);
break;
}
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
const body = {
'argument1': 123,
'argument2': 'my string',
'$callMode': 'AsyncRequestReply' // optional argument to force call mode to AsyncRequestReply
}
// if invocation is done by GET, place the parameters in query string and remove the 'Content-Type' header
const invokeRequestOptions = {
method: 'POST',
headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
body: JSON.stringify(body),
};
const redirectRequestOptions = {
method: "GET",
credentials: 'same-origin',
headers: new Headers({ Authorization: `Bearer ${token}` }),
redirect: "follow", // this option must be set to follow, otherwise an 'opaqueredirect' response is returned
};
const response = await fetch(url, invokeRequestOptions);
let newLocation = response.headers.get("Location");
// first response should be 202 and have a location header
console.log(`Got ${response.status}, with location: ${newLocation}`);
for (let i = 0; i < 20; i++) {
await sleep(SLEEP_DURATION);
// follow the location header to the new endpoint
const statusResponse = await fetch(newLocation, redirectRequestOptions);
// if the response was redirected (and automatically followed), then the output endpoint has been reached
// the output of the job can be found in the body of the response in JSON format
if (statusResponse.status != 200 || statusResponse.redirected)
{
// read the job output
const output = await statusResponse.json();
console.log(`Got ${statusResponse.status}, with body: ${JSON.stringify(output)}`);
break;
}
Este ejemplo ilustra cómo iniciar un trabajo a través de un desencadenador de API desde una aplicación basada en C#, utilizando el modo de llamada de sondeo asíncrono.
public async Task<string> AsyncPollingExample()
{
const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth
// create an http client that does not follow redirects and adds a bearer token on each call
var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var arguments = new Dictionary<string, object>
{
{ "argument1", 123 },
{ "argument2", "my string" },
{ "$callMode", "AsyncRequestReply" }, // optional argument to force call mode to AsyncRequestReply
};
var httpResponseStart = await httpClient.PostAsJsonAsync(url, arguments);
var redirectUri = httpResponseStart.Headers.Location;
if (httpResponseStart.StatusCode != HttpStatusCode.Accepted)
throw new Exception("Could not invoke workflow");
while (true)
{
var httpPollingResponse = await httpClient.GetAsync(redirectUri);
if (httpPollingResponse.StatusCode == HttpStatusCode.Redirect)
{
var outputLocation = httpPollingResponse.Headers.Location;
var outputResponse = await httpClient.GetAsync(outputLocation);
var jobOutput = await outputResponse.Content.ReadAsStringAsync();
return jobOutput;
}
await Task.Delay(1000);
}
}
public async Task<string> AsyncPollingExample()
{
const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth
// create an http client that does not follow redirects and adds a bearer token on each call
var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var arguments = new Dictionary<string, object>
{
{ "argument1", 123 },
{ "argument2", "my string" },
{ "$callMode", "AsyncRequestReply" }, // optional argument to force call mode to AsyncRequestReply
};
var httpResponseStart = await httpClient.PostAsJsonAsync(url, arguments);
var redirectUri = httpResponseStart.Headers.Location;
if (httpResponseStart.StatusCode != HttpStatusCode.Accepted)
throw new Exception("Could not invoke workflow");
while (true)
{
var httpPollingResponse = await httpClient.GetAsync(redirectUri);
if (httpPollingResponse.StatusCode == HttpStatusCode.Redirect)
{
var outputLocation = httpPollingResponse.Headers.Location;
var outputResponse = await httpClient.GetAsync(outputLocation);
var jobOutput = await outputResponse.Content.ReadAsStringAsync();
return jobOutput;
}
await Task.Delay(1000);
}
}
El modo de llamada inmediato devuelve un estado 200 OK al crearse correctamente el trabajo, sin ninguna otra información sobre el mismo.
Flujo de trabajo asíncrono en el que el trabajo se completa sin llamadas intermedias.
Este ejemplo ilustra cómo iniciar un trabajo a través de un desencadenador de API desde un explorador, utilizando el modo de llamada inmediato asíncrono.
const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
const body = {
'argument1': 123,
'argument2': 'my string',
'$callMode': 'FireAndForget' // optional argument to force call mode to FireAndForget
}
const options = {
method: 'POST',
headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
body: JSON.stringify(body),
};
let response = await fetch(url, options);
console.log(`Got ${response.status}`);
const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
const body = {
'argument1': 123,
'argument2': 'my string',
'$callMode': 'FireAndForget' // optional argument to force call mode to FireAndForget
}
const options = {
method: 'POST',
headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
body: JSON.stringify(body),
};
let response = await fetch(url, options);
console.log(`Got ${response.status}`);
Este ejemplo ilustra cómo iniciar un trabajo a través de un desencadenador de API desde una aplicación basada en C#, utilizando el modo de llamada inmediato asíncrono.
public async Task FireAndForgetExample()
{
const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth
// create an http client that does not follow redirects and adds Bearer <token> on each call
// if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var arguments = new Dictionary<string, object>
{
{ "argument1", 123 },
{ "argument2", "my string" },
{ "$callMode", "FireAndForget" }, // optional argument to force call mode to LongPolling
};
var response = await httpClient.PostAsJsonAsync(url, arguments);
Console.WriteLine(response.StatusCode);
}
public async Task FireAndForgetExample()
{
const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth
// create an http client that does not follow redirects and adds Bearer <token> on each call
// if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var arguments = new Dictionary<string, object>
{
{ "argument1", 123 },
{ "argument2", "my string" },
{ "$callMode", "FireAndForget" }, // optional argument to force call mode to LongPolling
};
var response = await httpClient.PostAsJsonAsync(url, arguments);
Console.WriteLine(response.StatusCode);
}
Este modo de llamada implica una llamada inicial que se bloquea y espera un tiempo a que se complete el trabajo, seguida de varias posibles llamadas de bloqueo y redireccionamientos. Por último, una vez finalizado el trabajo, se recupera el resultado del trabajo (salida o error).
En función de la configuración del tenant, la autenticación puede ser necesaria para todas las llamadas o solo para la llamada inicial.
Flujo de trabajo de sincronización (sondeo largo) en el que el resultado, ya sea correcto o incorrecto, se devuelve con la llamada inicial.
Flujo de trabajo de sincronización (sondeo largo) en el que se realizan automáticamente varias llamadas para completar el trabajo.
La llamada inicial se realiza utilizando el verbo HTTP configurado (OBTENER, PUBLICAR, PONER, ELIMINAR), que crea el trabajo asociado en Orchestrator. Una vez creado el trabajo con éxito, el sistema bloquea la llamada actual mientras espera a que se complete el trabajo. Cuando el trabajo finaliza, se libera la llamada bloqueada y se devuelve una respuesta que incluye los argumentos de salida del trabajo.
Si transcurrido un tiempo de espera el trabajo aún no ha finalizado, el sistema responde con un código de estado HTTP 303 (ver Otros) y redirige al URI de estado (a través del encabezado Ubicación). Debes seguir el URI de estado, que se bloquea hasta que se completa el trabajo. Si el trabajo no se completa después de un tiempo de espera, se te redirige de nuevo a la URI de estado, creando así un bucle de redirección. Una vez completado con éxito el trabajo, el resultado del trabajo (salida o error) se recupera como parte de la respuesta HTTP.
Por defecto, todas las llamadas deben incluir un token al portador válido para su autorización. Sin embargo, si no se selecciona la opción de configuración de tenant Requerir encabezado de autenticación para las redirecciones de desencadenadores de API de sincronización, solo la llamada inicial al desencadenador requiere el encabezado de autenticación. Las llamadas posteriores al punto final de estado pueden realizarse sin un encabezado de autorización.
La duración máxima del trabajo para este modo de llamada es de 15 minutos.
Este ejemplo ilustra cómo iniciar un trabajo a través de un desencadenador de API desde un explorador, utilizando el modo de llamada de sincronización (sondeo largo).
const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
const body = {
'argument1': 123,
'argument2': 'my string',
'$callMode': 'LongPolling' // optional argument to force call mode to LongPolling
}
const options = {
method: 'POST',
headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
body: JSON.stringify(body),
redirect: "follow", // follow redirects automatically
};
let response = await fetch(url, options);
const output = await response.json();
console.log(`Got ${response.status} with body ${JSON.stringify(output)}`);
const url = 'https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>';
const token = '<PERSONAL_ACCESS_TOKEN>'; // could also be an access token retrieved via OAuth
const body = {
'argument1': 123,
'argument2': 'my string',
'$callMode': 'LongPolling' // optional argument to force call mode to LongPolling
}
const options = {
method: 'POST',
headers: new Headers({ 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }),
body: JSON.stringify(body),
redirect: "follow", // follow redirects automatically
};
let response = await fetch(url, options);
const output = await response.json();
console.log(`Got ${response.status} with body ${JSON.stringify(output)}`);
Este ejemplo ilustra cómo iniciar un trabajo a través de un desencadenador de API desde una aplicación basada en C#, utilizando el modo de llamada de sincronización (sondeo largo).
public async Task SyncExample()
{
const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth
// create an http client that does not follow redirects and adds Bearer <token> on each call
// if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var arguments = new Dictionary<string, object>
{
{ "argument1", 123 },
{ "argument2", "my string" },
{ "$callMode", "LongPolling" }, // optional argument to force call mode to LongPolling
};
var response = await httpClient.PostAsJsonAsync(url, arguments);
while(response.StatusCode == HttpStatusCode.Redirect)
{
// in case of redirection, keep following the latest location in the header
var location = response.Headers.Location;
response = await httpClient.GetAsync(location);
}
// read the job output/error from the last request
var jobOutput = response.Content.ReadAsStringAsync();
Console.WriteLine(jobOutput);
}
public async Task SyncExample()
{
const string url = "https://cloud.uipath.com/{organizationName}/{tenantName}/orchestrator_/t/<INVOKE_URL>";
const string token = "<PERSONAL_ACCESS_TOKEN>"; // could also be an access token retrieved via OAuth
// create an http client that does not follow redirects and adds Bearer <token> on each call
// if the follow redirects option is enabled, C# will not add a bearer token by default after the redirect
var httpClient = new HttpClient(new HttpClientHandler { AllowAutoRedirect = false });
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var arguments = new Dictionary<string, object>
{
{ "argument1", 123 },
{ "argument2", "my string" },
{ "$callMode", "LongPolling" }, // optional argument to force call mode to LongPolling
};
var response = await httpClient.PostAsJsonAsync(url, arguments);
while(response.StatusCode == HttpStatusCode.Redirect)
{
// in case of redirection, keep following the latest location in the header
var location = response.Headers.Location;
response = await httpClient.GetAsync(location);
}
// read the job output/error from the last request
var jobOutput = response.Content.ReadAsStringAsync();
Console.WriteLine(jobOutput);
}