Skip to content

Commit

Permalink
feat(lib): add timeout abort controller on fetch (#276)
Browse files Browse the repository at this point in the history
  • Loading branch information
rodbustamante authored Jul 12, 2021
1 parent cbbb9a3 commit 377c590
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 219 deletions.
112 changes: 63 additions & 49 deletions lib/AdobeConnect/createMeeting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,67 +21,81 @@ export const createMeeting = async ({
/**
* Obtener `sco_id`.
*/
const getShortcutId = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'sco-shortcuts'
})
if (getShortcutId.response.results.status['@_code'] === 'ok') {
scoId = getShortcutId.response.results.shortcuts.sco.find(
short => short['@_type'] === 'user-meetings'
)['@_sco-id']
try {
const getShortcutId = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'sco-shortcuts'
})

if (getShortcutId.response.results.status['@_code'] === 'ok') {
scoId = getShortcutId.response.results.shortcuts.sco.find(
short => short['@_type'] === 'user-meetings'
)['@_sco-id']
}
} catch (err) {
throw new Error(err)
}

/**
* Validar si meeting ya existe.
*/
const checkMeeting = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'sco-contents',
'sco-id': scoId,
'filter-type': 'meeting',
'filter-name': name
})
if (
checkMeeting.response.results.status['@_code'] === 'ok' &&
checkMeeting.response.results.scos.sco
) {
return {
name,
dateInit,
scoId: checkMeeting.response.results.scos.sco['@_sco-id'],
url: url + checkMeeting.response.results.scos.sco['url-path'],
log: checkMeeting.log
try {
const checkMeeting = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'sco-contents',
'sco-id': scoId,
'filter-type': 'meeting',
'filter-name': name
})
if (
checkMeeting.response.results.status['@_code'] === 'ok' &&
checkMeeting.response.results.scos.sco
) {
return {
name,
dateInit,
scoId: checkMeeting.response.results.scos.sco['@_sco-id'],
url: url + checkMeeting.response.results.scos.sco['url-path'],
log: checkMeeting.log
}
}
} catch (err) {
throw new Error(err)
}

/**
* Crear meeting
*/
const createMeeting = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'sco-update',
type: 'meeting',
name,
'url-path': name.toLowerCase().replace(/\s/g, '-'),
'folder-id': scoId,
'date-begin': dateInit,
'date-end': dateEnd
})
try {
const createMeeting = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'sco-update',
type: 'meeting',
name,
'url-path': name.toLowerCase().replace(/\s/g, '-'),
'folder-id': scoId,
'date-begin': dateInit,
'date-end': dateEnd
})

if (
createMeeting.response.results.status['@_code'] !== 'ok' ||
!createMeeting.response.results.sco
) {
throw new Error(
'Bad response createMeeting: ' + createMeeting.response.results.statusText
)
}
if (
createMeeting.response.results.status['@_code'] !== 'ok' ||
!createMeeting.response.results.sco
) {
throw new Error(
'Bad response createMeeting: ' +
createMeeting.response.results.statusText
)
}

return {
name,
dateInit,
scoId: createMeeting.response.results.sco['@_sco-id'],
url: url + createMeeting.response.results.sco['url-path'],
log: createMeeting.log
return {
name,
dateInit,
scoId: createMeeting.response.results.sco['@_sco-id'],
url: url + createMeeting.response.results.sco['url-path'],
log: createMeeting.log
}
} catch (err) {
throw new Error(err)
}
}
96 changes: 52 additions & 44 deletions lib/AdobeConnect/createParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,63 @@ export const createParticipant = async (
token: string,
url: string
): Promise<Participant> => {
const { response, log } = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'principal-update',
'first-name': participant.firstName,
'last-name': participant.lastName,
email: participant.username,
login: participant.username,
password: participant.password,
type: 'external-user',
'send-email': 'false',
'has-children': 0
})

const {
results: { status, principal }
} = response
/**
* `OK` significa que la cuenta fue creada.
*/
if (status['@_code'] === 'ok') {
return {
principalId: principal['@_principal-id'],
accountId: principal['@_account-id'],
name: principal.name,
login: principal.login,
try {
const { response, log } = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'principal-update',
'first-name': participant.firstName,
'last-name': participant.lastName,
email: participant.username,
login: participant.username,
password: participant.password,
log
}
} else {
type: 'external-user',
'send-email': 'false',
'has-children': 0
})
const {
results: { status, principal }
} = response

/**
* `invalid` significa que la cuenta ya existe.
* `OK` significa que la cuenta fue creada.
*/
const getCreatedUser = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'principal-list',
'filter-like-login': participant.username
})
if (status['@_code'] === 'ok') {
return {
principalId: principal['@_principal-id'],
accountId: principal['@_account-id'],
name: principal.name,
login: principal.login,
email: participant.username,
password: participant.password,
log
}
} else {
/**
* `invalid` significa que la cuenta ya existe.
*/
try {
const getCreatedUser = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'principal-list',
'filter-like-login': participant.username
})

const principalUser =
getCreatedUser.response.results['principal-list'].principal
return {
principalId: principalUser['@_principal-id'],
accountId: principalUser['@_account-id'],
name: principalUser.name,
login: principalUser.login,
email: participant.username,
password: participant.password,
log: getCreatedUser.log
const principalUser =
getCreatedUser.response.results['principal-list'].principal
return {
principalId: principalUser['@_principal-id'],
accountId: principalUser['@_account-id'],
name: principalUser.name,
login: principalUser.login,
email: participant.username,
password: participant.password,
log: getCreatedUser.log
}
} catch (err) {
throw new Error(err)
}
}
} catch (err) {
throw new Error(err)
}
}
10 changes: 9 additions & 1 deletion lib/AdobeConnect/lib/fetchEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FetchEndpoint } from '../../'

import parser = require('fast-xml-parser')
import fetch = require('node-fetch')
import AbortController from 'abort-controller'

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const fetchEndpoint = async (
Expand All @@ -12,11 +13,16 @@ export const fetchEndpoint = async (
params: any,
debug = false
): Promise<FetchEndpoint> => {
const timeout = 8000
const endPointUrl = new URL(url)
Object.keys(params).forEach(key =>
endPointUrl.searchParams.append(key, params[`${key}`])
)
const response = await fetch(endPointUrl)
const controller = new AbortController()
const id = setTimeout(() => controller.abort(), timeout)
const response = await fetch(endPointUrl, {
signal: controller.signal
})
if (!response || !response.ok) {
throw new Error(`Network Error on fetch ${url}`)
}
Expand All @@ -39,6 +45,8 @@ export const fetchEndpoint = async (
if (!parsed.results) {
throw new Error(`Fetch error on ${url} when tried action ${params?.action}`)
}

clearTimeout(id)
return {
response: parsed,
log: {
Expand Down
27 changes: 15 additions & 12 deletions lib/AdobeConnect/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,22 @@ export const login = async ({
Object.keys(params).forEach(key =>
loginUrl.searchParams.append(key, params[`${key}`])
)
const response = await fetch(loginUrl)
try {
const response = await fetch(loginUrl)
if (!response.ok) {
throw new Error('Response Error')
}

if (!response.ok) {
throw new Error('Response Error')
}
const cookies = response.headers.get('set-cookie')
if (cookies === '' || !cookies.includes('BREEZESESSION')) {
throw new Error('Cookie BREEZESESSION not found in header')
}
const [[, breezeSession]] = cookies
.split(';')
.map(cookie => cookie.split('='))

const cookies = response.headers.get('set-cookie')
if (cookies === '' || !cookies.includes('BREEZESESSION')) {
throw new Error('Cookie BREEZESESSION not found in header')
return breezeSession
} catch (err) {
throw new Error(err)
}

const [[, breezeSession]] = cookies
.split(';')
.map(cookie => cookie.split('='))
return breezeSession
}
20 changes: 12 additions & 8 deletions lib/AdobeConnect/participantToMeeting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ export const participantToMeeting = async (
props: ParticipantToMeetingProps
): Promise<boolean> => {
const { scoId, principalId, permissionId, token, url } = props
const { response } = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'permissions-update',
'acl-id': scoId,
'principal-id': principalId,
'permission-id': permissionId
})
try {
const { response } = await fetchEndpoint(`${url}/api/xml`, {
session: token,
action: 'permissions-update',
'acl-id': scoId,
'principal-id': principalId,
'permission-id': permissionId
})

return response.results.status['@_code'] === 'ok'
return response.results.status['@_code'] === 'ok'
} catch (err) {
throw new Error(err)
}
}
25 changes: 14 additions & 11 deletions lib/Zoom/createMeeting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,20 @@ export const createMeeting = async (meeting: Meeting): Promise<Meeting> => {
schedule_for: scheduleFor,
settings
}
try {
const { response, log } = await fetchEndpoint({
token,
method: 'post',
pathUrl: `/users/${userId}/meetings`,
body: baseMeeting
})

const { response, log } = await fetchEndpoint({
token,
method: 'post',
pathUrl: `/users/${userId}/meetings`,
body: baseMeeting
})

return {
...response,
startUrl: response.start_url,
log
return {
...response,
startUrl: response.start_url,
log
}
} catch (err) {
throw new Error(err)
}
}
Loading

0 comments on commit 377c590

Please sign in to comment.